blob: ad0b44bf86aa133063553dc3f114a2241480262e [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020051
Willy Tarreaueb0c6142007-05-07 00:53:22 +020052#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010053#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020055#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020057#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020058#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020059#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020060#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020061#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010062#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020063#include <proto/lb_fwlc.h>
64#include <proto/lb_fwrr.h>
65#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020066#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020067#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010069#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020070#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010072#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020073#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020074#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020075#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010076#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020077#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010079#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080
Emeric Brunfc0421f2012-09-07 17:30:07 +020081#ifdef USE_OPENSSL
82#include <types/ssl_sock.h>
83#include <proto/ssl_sock.h>
84#include <proto/shctx.h>
85#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020086
Willy Tarreauf3c69202006-07-09 16:42:34 +020087/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
88 * ssl-hello-chk option to ensure that the remote server speaks SSL.
89 *
90 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
91 */
92const char sslv3_client_hello_pkt[] = {
93 "\x16" /* ContentType : 0x16 = Hanshake */
94 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
95 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
96 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
97 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
98 "\x03\x00" /* Hello Version : 0x0300 = v3 */
99 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
100 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
101 "\x00" /* Session ID length : empty (no session ID) */
102 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
103 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
104 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
105 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
106 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
107 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
108 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
109 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
110 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
111 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
112 "\x00\x38" "\x00\x39" "\x00\x3A"
113 "\x01" /* Compression Length : 0x01 = 1 byte for types */
114 "\x00" /* Compression Type : 0x00 = NULL compression */
115};
116
Willy Tarreau3842f002009-06-14 11:39:52 +0200117/* various keyword modifiers */
118enum kw_mod {
119 KWM_STD = 0, /* normal */
120 KWM_NO, /* "no" prefixed before the keyword */
121 KWM_DEF, /* "default" prefixed before the keyword */
122};
123
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100124/* permit to store configuration section */
125struct cfg_section {
126 struct list list;
127 char *section_name;
128 int (*section_parser)(const char *, int, char **, int);
129};
130
131/* Used to chain configuration sections definitions. This list
132 * stores struct cfg_section
133 */
134struct list sections = LIST_HEAD_INIT(sections);
135
Willy Tarreau13943ab2006-12-31 00:24:10 +0100136/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100137struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138 const char *name;
139 unsigned int val;
140 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100141 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100142 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100143};
144
145/* proxy->options */
146static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100147{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100148 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
149 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
150 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
151 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
152 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
153 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100154 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 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 Tarreau3986b9c2014-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 Tarreau3986b9c2014-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 Tarreau1058ae72014-12-23 22:40:40 +0100699 else if (!strcmp(args[0], "tune.buffers.reserve")) {
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.reserved_bufs = atol(args[1]);
706 if (global.tune.reserved_bufs < 2)
707 global.tune.reserved_bufs = 2;
708 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200709 else if (!strcmp(args[0], "tune.bufsize")) {
710 if (*(args[1]) == 0) {
711 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
712 err_code |= ERR_ALERT | ERR_FATAL;
713 goto out;
714 }
715 global.tune.bufsize = atol(args[1]);
716 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
717 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100718 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100719 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200720 }
721 else if (!strcmp(args[0], "tune.maxrewrite")) {
722 if (*(args[1]) == 0) {
723 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
724 err_code |= ERR_ALERT | ERR_FATAL;
725 goto out;
726 }
727 global.tune.maxrewrite = atol(args[1]);
728 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
729 global.tune.maxrewrite = global.tune.bufsize / 2;
730 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100731 else if (!strcmp(args[0], "tune.idletimer")) {
732 unsigned int idle;
733 const char *res;
734
735 if (*(args[1]) == 0) {
736 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
737 err_code |= ERR_ALERT | ERR_FATAL;
738 goto out;
739 }
740
741 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
742 if (res) {
743 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
744 file, linenum, *res, args[0]);
745 err_code |= ERR_ALERT | ERR_FATAL;
746 goto out;
747 }
748
749 if (idle > 65535) {
750 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 global.tune.idle_timer = idle;
755 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100756 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
757 if (global.tune.client_rcvbuf != 0) {
758 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
759 err_code |= ERR_ALERT;
760 goto out;
761 }
762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.client_rcvbuf = atol(args[1]);
768 }
769 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
770 if (global.tune.server_rcvbuf != 0) {
771 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
772 err_code |= ERR_ALERT;
773 goto out;
774 }
775 if (*(args[1]) == 0) {
776 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT | ERR_FATAL;
778 goto out;
779 }
780 global.tune.server_rcvbuf = atol(args[1]);
781 }
782 else if (!strcmp(args[0], "tune.sndbuf.client")) {
783 if (global.tune.client_sndbuf != 0) {
784 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
785 err_code |= ERR_ALERT;
786 goto out;
787 }
788 if (*(args[1]) == 0) {
789 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
790 err_code |= ERR_ALERT | ERR_FATAL;
791 goto out;
792 }
793 global.tune.client_sndbuf = atol(args[1]);
794 }
795 else if (!strcmp(args[0], "tune.sndbuf.server")) {
796 if (global.tune.server_sndbuf != 0) {
797 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
798 err_code |= ERR_ALERT;
799 goto out;
800 }
801 if (*(args[1]) == 0) {
802 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
803 err_code |= ERR_ALERT | ERR_FATAL;
804 goto out;
805 }
806 global.tune.server_sndbuf = atol(args[1]);
807 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200808 else if (!strcmp(args[0], "tune.pipesize")) {
809 if (*(args[1]) == 0) {
810 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
811 err_code |= ERR_ALERT | ERR_FATAL;
812 goto out;
813 }
814 global.tune.pipesize = atol(args[1]);
815 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100816 else if (!strcmp(args[0], "tune.http.cookielen")) {
817 if (*(args[1]) == 0) {
818 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
819 err_code |= ERR_ALERT | ERR_FATAL;
820 goto out;
821 }
822 global.tune.cookie_len = atol(args[1]) + 1;
823 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200824 else if (!strcmp(args[0], "tune.http.maxhdr")) {
825 if (*(args[1]) == 0) {
826 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
827 err_code |= ERR_ALERT | ERR_FATAL;
828 goto out;
829 }
830 global.tune.max_http_hdr = atol(args[1]);
831 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100832 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
833#ifdef USE_ZLIB
834 if (*args[1]) {
835 global.tune.zlibmemlevel = atoi(args[1]);
836 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
837 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
838 file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 } else {
843 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
844 file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
848#else
849 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
850 err_code |= ERR_ALERT | ERR_FATAL;
851 goto out;
852#endif
853 }
854 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
855#ifdef USE_ZLIB
856 if (*args[1]) {
857 global.tune.zlibwindowsize = atoi(args[1]);
858 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
859 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
860 file, linenum, args[0]);
861 err_code |= ERR_ALERT | ERR_FATAL;
862 goto out;
863 }
864 } else {
865 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
866 file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869 }
870#else
871 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874#endif
875 }
William Lallemandf3747832012-11-09 12:33:10 +0100876 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
877 if (*args[1]) {
878 global.tune.comp_maxlevel = atoi(args[1]);
879 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
880 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
881 file, linenum, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885 } else {
886 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
887 file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 else if (!strcmp(args[0], "uid")) {
893 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200894 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT;
896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
898 if (*(args[1]) == 0) {
899 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200900 err_code |= ERR_ALERT | ERR_FATAL;
901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200902 }
903 global.uid = atol(args[1]);
904 }
905 else if (!strcmp(args[0], "gid")) {
906 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200907 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT;
909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 if (*(args[1]) == 0) {
912 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 }
916 global.gid = atol(args[1]);
917 }
Simon Horman98637e52014-06-20 12:30:16 +0900918 else if (!strcmp(args[0], "external-check")) {
919 global.external_check = 1;
920 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200921 /* user/group name handling */
922 else if (!strcmp(args[0], "user")) {
923 struct passwd *ha_user;
924 if (global.uid != 0) {
925 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200926 err_code |= ERR_ALERT;
927 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200928 }
929 errno = 0;
930 ha_user = getpwnam(args[1]);
931 if (ha_user != NULL) {
932 global.uid = (int)ha_user->pw_uid;
933 }
934 else {
935 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 +0200936 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200937 }
938 }
939 else if (!strcmp(args[0], "group")) {
940 struct group *ha_group;
941 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200942 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT;
944 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200945 }
946 errno = 0;
947 ha_group = getgrnam(args[1]);
948 if (ha_group != NULL) {
949 global.gid = (int)ha_group->gr_gid;
950 }
951 else {
952 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 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200954 }
955 }
956 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 if (*(args[1]) == 0) {
959 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT | ERR_FATAL;
961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200962 }
963 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100964 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
965 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
966 file, linenum, args[0], LONGBITS, global.nbproc);
967 err_code |= ERR_ALERT | ERR_FATAL;
968 goto out;
969 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200970 }
971 else if (!strcmp(args[0], "maxconn")) {
972 if (global.maxconn != 0) {
973 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200974 err_code |= ERR_ALERT;
975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200976 }
977 if (*(args[1]) == 0) {
978 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200981 }
982 global.maxconn = atol(args[1]);
983#ifdef SYSTEM_MAXCONN
984 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
985 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);
986 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200987 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200988 }
989#endif /* SYSTEM_MAXCONN */
990 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200991 else if (!strcmp(args[0], "maxsslconn")) {
992#ifdef USE_OPENSSL
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
997 }
998 global.maxsslconn = atol(args[1]);
999#else
Emeric Brun0914df82012-10-02 18:45:42 +02001000 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1001 err_code |= ERR_ALERT | ERR_FATAL;
1002 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001003#endif
1004 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001005 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1006#ifdef USE_OPENSSL
1007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 free(global.listen_default_ciphers);
1013 global.listen_default_ciphers = strdup(args[1]);
1014#else
1015 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018#endif
1019 }
1020 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1021#ifdef USE_OPENSSL
1022 if (*(args[1]) == 0) {
1023 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1024 err_code |= ERR_ALERT | ERR_FATAL;
1025 goto out;
1026 }
1027 free(global.connect_default_ciphers);
1028 global.connect_default_ciphers = strdup(args[1]);
1029#else
1030 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1031 err_code |= ERR_ALERT | ERR_FATAL;
1032 goto out;
1033#endif
1034 }
Emeric Brun850efd52014-01-29 12:24:34 +01001035 else if (!strcmp(args[0], "ssl-server-verify")) {
1036 if (*(args[1]) == 0) {
1037 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1038 err_code |= ERR_ALERT | ERR_FATAL;
1039 goto out;
1040 }
1041 if (strcmp(args[1],"none") == 0)
1042 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1043 else if (strcmp(args[1],"required") == 0)
1044 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1045 else {
1046 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001051 else if (!strcmp(args[0], "maxconnrate")) {
1052 if (global.cps_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.cps_lim = atol(args[1]);
1063 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001064 else if (!strcmp(args[0], "maxsessrate")) {
1065 if (global.sps_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.sps_lim = atol(args[1]);
1076 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001077 else if (!strcmp(args[0], "maxsslrate")) {
1078 if (global.ssl_lim != 0) {
1079 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT;
1081 goto out;
1082 }
1083 if (*(args[1]) == 0) {
1084 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1085 err_code |= ERR_ALERT | ERR_FATAL;
1086 goto out;
1087 }
1088 global.ssl_lim = atol(args[1]);
1089 }
William Lallemandd85f9172012-11-09 17:05:39 +01001090 else if (!strcmp(args[0], "maxcomprate")) {
1091 if (*(args[1]) == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
1095 }
1096 global.comp_rate_lim = atoi(args[1]) * 1024;
1097 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001098 else if (!strcmp(args[0], "maxpipes")) {
1099 if (global.maxpipes != 0) {
1100 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001101 err_code |= ERR_ALERT;
1102 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001103 }
1104 if (*(args[1]) == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001108 }
1109 global.maxpipes = atol(args[1]);
1110 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001111 else if (!strcmp(args[0], "maxzlibmem")) {
1112 if (*(args[1]) == 0) {
1113 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1114 err_code |= ERR_ALERT | ERR_FATAL;
1115 goto out;
1116 }
William Lallemande3a7d992012-11-20 11:25:20 +01001117 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001118 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001119 else if (!strcmp(args[0], "maxcompcpuusage")) {
1120 if (*(args[1]) == 0) {
1121 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
1124 }
1125 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001126 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001127 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
1130 }
1131}
1132
Willy Tarreaubaaee002006-06-26 02:48:02 +02001133 else if (!strcmp(args[0], "ulimit-n")) {
1134 if (global.rlimit_nofile != 0) {
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 an integer 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.rlimit_nofile = atol(args[1]);
1145 }
1146 else if (!strcmp(args[0], "chroot")) {
1147 if (global.chroot != NULL) {
1148 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001149 err_code |= ERR_ALERT;
1150 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001151 }
1152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.chroot = strdup(args[1]);
1158 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001159 else if (!strcmp(args[0], "description")) {
1160 int i, len=0;
1161 char *d;
1162
1163 if (!*args[1]) {
1164 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1165 file, linenum, args[0]);
1166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
1168 }
1169
Willy Tarreau348acfe2014-04-14 15:00:39 +02001170 for (i = 1; *args[i]; i++)
1171 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001172
1173 if (global.desc)
1174 free(global.desc);
1175
1176 global.desc = d = (char *)calloc(1, len);
1177
Willy Tarreau348acfe2014-04-14 15:00:39 +02001178 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1179 for (i = 2; *args[i]; i++)
1180 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001181 }
1182 else if (!strcmp(args[0], "node")) {
1183 int i;
1184 char c;
1185
1186 for (i=0; args[1][i]; i++) {
1187 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001188 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1189 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001190 break;
1191 }
1192
1193 if (!i || args[1][i]) {
1194 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1195 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1196 file, linenum, args[0]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200
1201 if (global.node)
1202 free(global.node);
1203
1204 global.node = strdup(args[1]);
1205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001206 else if (!strcmp(args[0], "pidfile")) {
1207 if (global.pidfile != NULL) {
1208 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001209 err_code |= ERR_ALERT;
1210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001211 }
1212 if (*(args[1]) == 0) {
1213 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001216 }
1217 global.pidfile = strdup(args[1]);
1218 }
Emeric Bruned760922010-10-22 17:59:25 +02001219 else if (!strcmp(args[0], "unix-bind")) {
1220 int cur_arg = 1;
1221 while (*(args[cur_arg])) {
1222 if (!strcmp(args[cur_arg], "prefix")) {
1223 if (global.unix_bind.prefix != NULL) {
1224 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1225 err_code |= ERR_ALERT;
1226 cur_arg += 2;
1227 continue;
1228 }
1229
1230 if (*(args[cur_arg+1]) == 0) {
1231 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1232 err_code |= ERR_ALERT | ERR_FATAL;
1233 goto out;
1234 }
1235 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1236 cur_arg += 2;
1237 continue;
1238 }
1239
1240 if (!strcmp(args[cur_arg], "mode")) {
1241
1242 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1243 cur_arg += 2;
1244 continue;
1245 }
1246
1247 if (!strcmp(args[cur_arg], "uid")) {
1248
1249 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1250 cur_arg += 2;
1251 continue;
1252 }
1253
1254 if (!strcmp(args[cur_arg], "gid")) {
1255
1256 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1257 cur_arg += 2;
1258 continue;
1259 }
1260
1261 if (!strcmp(args[cur_arg], "user")) {
1262 struct passwd *user;
1263
1264 user = getpwnam(args[cur_arg + 1]);
1265 if (!user) {
1266 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1267 file, linenum, args[0], args[cur_arg + 1 ]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271
1272 global.unix_bind.ux.uid = user->pw_uid;
1273 cur_arg += 2;
1274 continue;
1275 }
1276
1277 if (!strcmp(args[cur_arg], "group")) {
1278 struct group *group;
1279
1280 group = getgrnam(args[cur_arg + 1]);
1281 if (!group) {
1282 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1283 file, linenum, args[0], args[cur_arg + 1 ]);
1284 err_code |= ERR_ALERT | ERR_FATAL;
1285 goto out;
1286 }
1287
1288 global.unix_bind.ux.gid = group->gr_gid;
1289 cur_arg += 2;
1290 continue;
1291 }
1292
Willy Tarreaub48f9582011-09-05 01:17:06 +02001293 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001294 file, linenum, args[0]);
1295 err_code |= ERR_ALERT | ERR_FATAL;
1296 goto out;
1297 }
1298 }
William Lallemand0f99e342011-10-12 17:50:54 +02001299 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1300 /* delete previous herited or defined syslog servers */
1301 struct logsrv *back;
1302 struct logsrv *tmp;
1303
1304 if (*(args[1]) != 0) {
1305 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1306 err_code |= ERR_ALERT | ERR_FATAL;
1307 goto out;
1308 }
1309
1310 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1311 LIST_DEL(&tmp->list);
1312 free(tmp);
1313 }
1314 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001315 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001316 struct sockaddr_storage *sk;
1317 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001318 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001319 int arg = 0;
1320 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001321
Willy Tarreaubaaee002006-06-26 02:48:02 +02001322 if (*(args[1]) == 0 || *(args[2]) == 0) {
1323 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001324 err_code |= ERR_ALERT | ERR_FATAL;
1325 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001326 }
William Lallemand0f99e342011-10-12 17:50:54 +02001327
1328 logsrv = calloc(1, sizeof(struct logsrv));
1329
Willy Tarreau18324f52014-06-27 18:10:07 +02001330 /* just after the address, a length may be specified */
1331 if (strcmp(args[arg+2], "len") == 0) {
1332 len = atoi(args[arg+3]);
1333 if (len < 80 || len > 65535) {
1334 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1335 file, linenum, args[arg+3]);
1336 err_code |= ERR_ALERT | ERR_FATAL;
1337 goto out;
1338 }
1339 logsrv->maxlen = len;
1340
1341 /* skip these two args */
1342 arg += 2;
1343 }
1344 else
1345 logsrv->maxlen = MAX_SYSLOG_LEN;
1346
1347 if (logsrv->maxlen > global.max_syslog_len) {
1348 global.max_syslog_len = logsrv->maxlen;
1349 logline = realloc(logline, global.max_syslog_len + 1);
1350 }
1351
1352 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001353 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001354 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001355 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001356 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 }
1358
William Lallemand0f99e342011-10-12 17:50:54 +02001359 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001360 if (*(args[arg+3])) {
1361 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001362 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001363 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001364 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001365 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 }
1367 }
1368
William Lallemand0f99e342011-10-12 17:50:54 +02001369 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001370 if (*(args[arg+4])) {
1371 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001372 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001373 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001374 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001375 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001376 }
1377 }
1378
Willy Tarreau902636f2013-03-10 19:44:48 +01001379 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001380 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001381 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001382 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001383 free(logsrv);
1384 goto out;
1385 }
1386 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001387
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001388 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001389 if (port1 != port2) {
1390 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1391 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001392 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001393 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001394 goto out;
1395 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001396
William Lallemand0f99e342011-10-12 17:50:54 +02001397 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001398 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001399 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001400 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401
William Lallemand0f99e342011-10-12 17:50:54 +02001402 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001403 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001404 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1405 char *name;
1406 int len;
1407
1408 if (global.log_send_hostname != NULL) {
1409 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1410 err_code |= ERR_ALERT;
1411 goto out;
1412 }
1413
1414 if (*(args[1]))
1415 name = args[1];
1416 else
1417 name = hostname;
1418
1419 len = strlen(name);
1420
1421 /* We'll add a space after the name to respect the log format */
1422 free(global.log_send_hostname);
1423 global.log_send_hostname = malloc(len + 2);
1424 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1425 }
Kevinm48936af2010-12-22 16:08:21 +00001426 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1427 if (*(args[1]) == 0) {
1428 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
1431 }
1432 free(global.log_tag);
1433 global.log_tag = strdup(args[1]);
1434 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001435 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1436 if (global.spread_checks != 0) {
1437 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001438 err_code |= ERR_ALERT;
1439 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001440 }
1441 if (*(args[1]) == 0) {
1442 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001443 err_code |= ERR_ALERT | ERR_FATAL;
1444 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001445 }
1446 global.spread_checks = atol(args[1]);
1447 if (global.spread_checks < 0 || global.spread_checks > 50) {
1448 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001449 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001450 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001451 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001452 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1453 const char *err;
1454 unsigned int val;
1455
1456
1457 if (*(args[1]) == 0) {
1458 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1459 err_code |= ERR_ALERT | ERR_FATAL;
1460 goto out;
1461 }
1462
1463 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1464 if (err) {
1465 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 }
1468 global.max_spread_checks = val;
1469 if (global.max_spread_checks < 0) {
1470 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1471 err_code |= ERR_ALERT | ERR_FATAL;
1472 }
1473 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001474 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1475#ifdef USE_CPU_AFFINITY
1476 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001477 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001478 unsigned long cpus = 0;
1479
1480 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001481 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001482 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001483 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001484 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001485 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001486 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001487 proc = atol(args[1]);
1488 if (proc >= 1 && proc <= LONGBITS)
1489 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001490 }
1491
1492 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001493 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",
1494 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001495 err_code |= ERR_ALERT | ERR_FATAL;
1496 goto out;
1497 }
1498
1499 cur_arg = 2;
1500 while (*args[cur_arg]) {
1501 unsigned int low, high;
1502
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001503 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001504 char *dash = strchr(args[cur_arg], '-');
1505
1506 low = high = str2uic(args[cur_arg]);
1507 if (dash)
1508 high = str2uic(dash + 1);
1509
1510 if (high < low) {
1511 unsigned int swap = low;
1512 low = high;
1513 high = swap;
1514 }
1515
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001516 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001517 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001518 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001519 err_code |= ERR_ALERT | ERR_FATAL;
1520 goto out;
1521 }
1522
1523 while (low <= high)
1524 cpus |= 1UL << low++;
1525 }
1526 else {
1527 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1528 file, linenum, args[0], args[cur_arg]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532 cur_arg++;
1533 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001534 for (i = 0; i < LONGBITS; i++)
1535 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001536 global.cpu_map[i] = cpus;
1537#else
1538 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1539 err_code |= ERR_ALERT | ERR_FATAL;
1540 goto out;
1541#endif
1542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001544 struct cfg_kw_list *kwl;
1545 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001546 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001547
1548 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1549 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1550 if (kwl->kw[index].section != CFG_GLOBAL)
1551 continue;
1552 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001553 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001554 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001555 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001556 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001557 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001558 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001559 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001560 err_code |= ERR_WARN;
1561 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001562 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001563 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001564 }
1565 }
1566 }
1567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001569 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001570 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001571
Willy Tarreau058e9072009-07-20 09:30:05 +02001572 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001573 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001574 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575}
1576
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001577void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001579 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001580 defproxy.mode = PR_MODE_TCP;
1581 defproxy.state = PR_STNEW;
1582 defproxy.maxconn = cfg_maxpconn;
1583 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001584
Simon Horman66183002013-02-23 10:16:43 +09001585 defproxy.defsrv.check.inter = DEF_CHKINTR;
1586 defproxy.defsrv.check.fastinter = 0;
1587 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001588 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1589 defproxy.defsrv.agent.fastinter = 0;
1590 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001591 defproxy.defsrv.check.rise = DEF_RISETIME;
1592 defproxy.defsrv.check.fall = DEF_FALLTIME;
1593 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1594 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001595 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001596 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001597 defproxy.defsrv.maxqueue = 0;
1598 defproxy.defsrv.minconn = 0;
1599 defproxy.defsrv.maxconn = 0;
1600 defproxy.defsrv.slowstart = 0;
1601 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1602 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1603 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001604}
1605
Willy Tarreauade5ec42010-01-28 19:33:49 +01001606
Willy Tarreau63af98d2014-05-18 08:11:41 +02001607/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1608 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1609 * ERR_FATAL in case of error.
1610 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001611static int create_cond_regex_rule(const char *file, int line,
1612 struct proxy *px, int dir, int action, int flags,
1613 const char *cmd, const char *reg, const char *repl,
1614 const char **cond_start)
1615{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001616 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001617 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001618 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001619 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001620 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001621 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001622 int cs;
1623 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001624
1625 if (px == &defproxy) {
1626 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001627 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001628 goto err;
1629 }
1630
1631 if (*reg == 0) {
1632 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001633 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001634 goto err;
1635 }
1636
1637 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001638 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001639
Willy Tarreau5321c422010-01-28 20:35:13 +01001640 if (cond_start &&
1641 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001642 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1643 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1644 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001645 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001646 goto err;
1647 }
1648 }
1649 else if (cond_start && **cond_start) {
1650 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1651 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001652 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001653 goto err;
1654 }
1655
Willy Tarreau63af98d2014-05-18 08:11:41 +02001656 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001657 (dir == SMP_OPT_DIR_REQ) ?
1658 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1659 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1660 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001661
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001662 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001663 if (!preg) {
1664 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001665 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001666 goto err;
1667 }
1668
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001669 cs = !(flags & REG_ICASE);
1670 cap = !(flags & REG_NOSUB);
1671 error = NULL;
1672 if (!regex_comp(reg, preg, cs, cap, &error)) {
1673 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1674 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001675 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001676 goto err;
1677 }
1678
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001679 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001680 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001681 if (repl && err) {
1682 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1683 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001684 ret_code |= ERR_ALERT | ERR_FATAL;
1685 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001686 }
1687
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001688 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001689 ret_code |= ERR_WARN;
1690
1691 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001692
Willy Tarreau63af98d2014-05-18 08:11:41 +02001693 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001694 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001695 err:
1696 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001697 free(errmsg);
1698 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001699}
1700
Willy Tarreaubaaee002006-06-26 02:48:02 +02001701/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001702 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001703 * Returns the error code, 0 if OK, or any combination of :
1704 * - ERR_ABORT: must abort ASAP
1705 * - ERR_FATAL: we can continue parsing but not start the service
1706 * - ERR_WARN: a warning has been emitted
1707 * - ERR_ALERT: an alert has been emitted
1708 * Only the two first ones can stop processing, the two others are just
1709 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001710 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001711int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1712{
1713 static struct peers *curpeers = NULL;
1714 struct peer *newpeer = NULL;
1715 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001716 struct bind_conf *bind_conf;
1717 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001718 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001719 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001720
1721 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001722 if (!*args[1]) {
1723 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001724 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001725 goto out;
1726 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001727
1728 err = invalid_char(args[1]);
1729 if (err) {
1730 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1731 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001732 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001733 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001734 }
1735
1736 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1737 /*
1738 * If there are two proxies with the same name only following
1739 * combinations are allowed:
1740 */
1741 if (strcmp(curpeers->id, args[1]) == 0) {
1742 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1743 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1744 err_code |= ERR_WARN;
1745 }
1746 }
1747
1748 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1749 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1750 err_code |= ERR_ALERT | ERR_ABORT;
1751 goto out;
1752 }
1753
1754 curpeers->next = peers;
1755 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001756 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001757 curpeers->conf.line = linenum;
1758 curpeers->last_change = now.tv_sec;
1759 curpeers->id = strdup(args[1]);
1760 }
1761 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001762 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001763 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001764 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001765
1766 if (!*args[2]) {
1767 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1768 file, linenum, args[0]);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 goto out;
1771 }
1772
1773 err = invalid_char(args[1]);
1774 if (err) {
1775 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1776 file, linenum, *err, args[1]);
1777 err_code |= ERR_ALERT | ERR_FATAL;
1778 goto out;
1779 }
1780
1781 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1782 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1783 err_code |= ERR_ALERT | ERR_ABORT;
1784 goto out;
1785 }
1786
1787 /* the peers are linked backwards first */
1788 curpeers->count++;
1789 newpeer->next = curpeers->remote;
1790 curpeers->remote = newpeer;
1791 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001792 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001793 newpeer->conf.line = linenum;
1794
1795 newpeer->last_change = now.tv_sec;
1796 newpeer->id = strdup(args[1]);
1797
Willy Tarreau902636f2013-03-10 19:44:48 +01001798 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001799 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001800 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001801 err_code |= ERR_ALERT | ERR_FATAL;
1802 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001803 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001804
1805 proto = protocol_by_family(sk->ss_family);
1806 if (!proto || !proto->connect) {
1807 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1808 file, linenum, args[0], args[1]);
1809 err_code |= ERR_ALERT | ERR_FATAL;
1810 goto out;
1811 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001812
1813 if (port1 != port2) {
1814 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1815 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001816 err_code |= ERR_ALERT | ERR_FATAL;
1817 goto out;
1818 }
1819
Willy Tarreau2aa38802013-02-20 19:20:59 +01001820 if (!port1) {
1821 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1822 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001823 err_code |= ERR_ALERT | ERR_FATAL;
1824 goto out;
1825 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001826
Emeric Brun32da3c42010-09-23 18:39:19 +02001827 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001828 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001829 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001830 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001831
Emeric Brun32da3c42010-09-23 18:39:19 +02001832 if (strcmp(newpeer->id, localpeer) == 0) {
1833 /* Current is local peer, it define a frontend */
1834 newpeer->local = 1;
1835
1836 if (!curpeers->peers_fe) {
1837 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1838 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1839 err_code |= ERR_ALERT | ERR_ABORT;
1840 goto out;
1841 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001842
Willy Tarreau237250c2011-07-29 01:49:03 +02001843 init_new_proxy(curpeers->peers_fe);
1844 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001845
1846 curpeers->peers_fe->last_change = now.tv_sec;
1847 curpeers->peers_fe->id = strdup(args[1]);
1848 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001849 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001850 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1851 curpeers->peers_fe->timeout.connect = 5000;
1852 curpeers->peers_fe->accept = peer_accept;
1853 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001854 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1855 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001856
1857 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1858
Willy Tarreau902636f2013-03-10 19:44:48 +01001859 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1860 if (errmsg && *errmsg) {
1861 indent_msg(&errmsg, 2);
1862 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001863 }
1864 else
1865 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1866 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001867 err_code |= ERR_FATAL;
1868 goto out;
1869 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001870
1871 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001872 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001873 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1874 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1875 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1876 l->accept = session_accept;
1877 l->handler = process_session;
1878 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1879 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1880 global.maxsock += l->maxconn;
1881 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001882 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001883 else {
1884 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1885 file, linenum, args[0], args[1],
1886 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1887 err_code |= ERR_FATAL;
1888 goto out;
1889 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001890 }
1891 } /* neither "peer" nor "peers" */
1892 else if (*args[0] != 0) {
1893 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
1896 }
1897
1898out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001899 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001900 return err_code;
1901}
1902
Willy Tarreau3842f002009-06-14 11:39:52 +02001903int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001904{
1905 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001906 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001907 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001908 int rc;
1909 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001910 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001911 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001912 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001913 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001914 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001915
Willy Tarreau977b8e42006-12-29 14:19:17 +01001916 if (!strcmp(args[0], "listen"))
1917 rc = PR_CAP_LISTEN;
1918 else if (!strcmp(args[0], "frontend"))
1919 rc = PR_CAP_FE | PR_CAP_RS;
1920 else if (!strcmp(args[0], "backend"))
1921 rc = PR_CAP_BE | PR_CAP_RS;
1922 else if (!strcmp(args[0], "ruleset"))
1923 rc = PR_CAP_RS;
1924 else
1925 rc = PR_CAP_NONE;
1926
1927 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001928 struct ebpt_node *node;
1929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930 if (!*args[1]) {
1931 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1932 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1933 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001934 err_code |= ERR_ALERT | ERR_ABORT;
1935 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001937
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001938 err = invalid_char(args[1]);
1939 if (err) {
1940 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1941 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001942 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001943 }
1944
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001945 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1946 curproxy = container_of(node, struct proxy, conf.by_name);
1947
1948 if (strcmp(curproxy->id, args[1]) != 0)
1949 break;
1950
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001951 /*
1952 * If there are two proxies with the same name only following
1953 * combinations are allowed:
1954 *
1955 * listen backend frontend ruleset
1956 * listen - - - -
1957 * backend - - OK -
1958 * frontend - OK - -
1959 * ruleset - - - -
1960 */
1961
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001962 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1963 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001964 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1965 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1966 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001967 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001968 }
1969 }
1970
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1972 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001973 err_code |= ERR_ALERT | ERR_ABORT;
1974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001975 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001976
Willy Tarreau97cb7802010-01-03 20:23:58 +01001977 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978 curproxy->next = proxy;
1979 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001980 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1981 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001982 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001984 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001985 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001986
1987 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001988 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001989 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001990
Willy Tarreau4348fad2012-09-20 16:48:07 +02001991 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1992
Willy Tarreau902636f2013-03-10 19:44:48 +01001993 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1994 if (errmsg && *errmsg) {
1995 indent_msg(&errmsg, 2);
1996 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001997 }
1998 else
1999 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2000 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002001 err_code |= ERR_FATAL;
2002 goto out;
2003 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002004
Willy Tarreau4348fad2012-09-20 16:48:07 +02002005 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002006 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002007 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002008 }
2009
2010 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002011 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002012 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002013
Willy Tarreaubaaee002006-06-26 02:48:02 +02002014 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002015 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002016 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002017 curproxy->no_options = defproxy.no_options;
2018 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002019 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002020 curproxy->except_net = defproxy.except_net;
2021 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002022 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002023 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002025 if (defproxy.fwdfor_hdr_len) {
2026 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2027 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2028 }
2029
Willy Tarreaub86db342009-11-30 11:50:16 +01002030 if (defproxy.orgto_hdr_len) {
2031 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2032 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2033 }
2034
Mark Lamourinec2247f02012-01-04 13:02:01 -05002035 if (defproxy.server_id_hdr_len) {
2036 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2037 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2038 }
2039
Willy Tarreau977b8e42006-12-29 14:19:17 +01002040 if (curproxy->cap & PR_CAP_FE) {
2041 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002042 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002043 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002044
2045 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002046 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2047 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002048
2049 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2050 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002051
Willy Tarreau977b8e42006-12-29 14:19:17 +01002052 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002053 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002054 curproxy->fullconn = defproxy.fullconn;
2055 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002056 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002057
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002058 if (defproxy.check_req) {
2059 curproxy->check_req = calloc(1, defproxy.check_len);
2060 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2061 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002062 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002064 if (defproxy.expect_str) {
2065 curproxy->expect_str = strdup(defproxy.expect_str);
2066 if (defproxy.expect_regex) {
2067 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002068 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2069 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002070 }
2071 }
2072
Willy Tarreau67402132012-05-31 20:40:20 +02002073 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002074 if (defproxy.cookie_name)
2075 curproxy->cookie_name = strdup(defproxy.cookie_name);
2076 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002077 if (defproxy.cookie_domain)
2078 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002079
Willy Tarreau31936852010-10-06 16:59:56 +02002080 if (defproxy.cookie_maxidle)
2081 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2082
2083 if (defproxy.cookie_maxlife)
2084 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2085
Emeric Brun647caf12009-06-30 17:57:00 +02002086 if (defproxy.rdp_cookie_name)
2087 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2088 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2089
Willy Tarreau01732802007-11-01 22:48:15 +01002090 if (defproxy.url_param_name)
2091 curproxy->url_param_name = strdup(defproxy.url_param_name);
2092 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002093
Benoitaffb4812009-03-25 13:02:10 +01002094 if (defproxy.hh_name)
2095 curproxy->hh_name = strdup(defproxy.hh_name);
2096 curproxy->hh_len = defproxy.hh_len;
2097 curproxy->hh_match_domain = defproxy.hh_match_domain;
2098
Willy Tarreauef9a3602012-12-08 22:29:20 +01002099 if (defproxy.conn_src.iface_name)
2100 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2101 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002102 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002103#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002104 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002105#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002108 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002109 if (defproxy.capture_name)
2110 curproxy->capture_name = strdup(defproxy.capture_name);
2111 curproxy->capture_namelen = defproxy.capture_namelen;
2112 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002114
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002116 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002117 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002118 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002119 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002120 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002121 curproxy->mon_net = defproxy.mon_net;
2122 curproxy->mon_mask = defproxy.mon_mask;
2123 if (defproxy.monitor_uri)
2124 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2125 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002126 if (defproxy.defbe.name)
2127 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002128
2129 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002130 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2131 if (curproxy->conf.logformat_string &&
2132 curproxy->conf.logformat_string != default_http_log_format &&
2133 curproxy->conf.logformat_string != default_tcp_log_format &&
2134 curproxy->conf.logformat_string != clf_http_log_format)
2135 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2136
2137 if (defproxy.conf.lfs_file) {
2138 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2139 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2140 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002141 }
2142
2143 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002144 curproxy->timeout.connect = defproxy.timeout.connect;
2145 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002146 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002147 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002148 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002149 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002150 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002151 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002152 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002153 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154 }
2155
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002157 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002158
2159 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002160 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002161 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002162 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002163 LIST_INIT(&node->list);
2164 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2165 }
2166
Willy Tarreau62a61232013-04-12 18:13:46 +02002167 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2168 if (curproxy->conf.uniqueid_format_string)
2169 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2170
2171 if (defproxy.conf.uif_file) {
2172 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2173 curproxy->conf.uif_line = defproxy.conf.uif_line;
2174 }
William Lallemanda73203e2012-03-12 12:48:57 +01002175
2176 /* copy default header unique id */
2177 if (defproxy.header_unique_id)
2178 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2179
William Lallemand82fe75c2012-10-23 10:25:10 +02002180 /* default compression options */
2181 if (defproxy.comp != NULL) {
2182 curproxy->comp = calloc(1, sizeof(struct comp));
2183 curproxy->comp->algos = defproxy.comp->algos;
2184 curproxy->comp->types = defproxy.comp->types;
2185 }
2186
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002188 curproxy->conf.used_listener_id = EB_ROOT;
2189 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002190
Simon Horman98637e52014-06-20 12:30:16 +09002191 if (defproxy.check_path)
2192 curproxy->check_path = strdup(defproxy.check_path);
2193 if (defproxy.check_command)
2194 curproxy->check_command = strdup(defproxy.check_command);
2195
Willy Tarreau93893792009-07-23 13:19:11 +02002196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
2198 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2199 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002200 /* FIXME-20070101: we should do this too at the end of the
2201 * config parsing to free all default values.
2202 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002203 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002204 free(defproxy.check_command);
2205 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002206 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002207 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002208 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002209 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002210 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002211 free(defproxy.capture_name);
2212 free(defproxy.monitor_uri);
2213 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002214 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002215 free(defproxy.fwdfor_hdr_name);
2216 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002217 free(defproxy.orgto_hdr_name);
2218 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002219 free(defproxy.server_id_hdr_name);
2220 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002221 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002222 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002223 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002224 free(defproxy.expect_regex);
2225 defproxy.expect_regex = NULL;
2226 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002227
Willy Tarreau62a61232013-04-12 18:13:46 +02002228 if (defproxy.conf.logformat_string != default_http_log_format &&
2229 defproxy.conf.logformat_string != default_tcp_log_format &&
2230 defproxy.conf.logformat_string != clf_http_log_format)
2231 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002232
Willy Tarreau62a61232013-04-12 18:13:46 +02002233 free(defproxy.conf.uniqueid_format_string);
2234 free(defproxy.conf.lfs_file);
2235 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002236
Willy Tarreaua534fea2008-08-03 12:19:50 +02002237 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002238 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002239
Willy Tarreaubaaee002006-06-26 02:48:02 +02002240 /* we cannot free uri_auth because it might already be used */
2241 init_default_instance();
2242 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002243 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2244 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002245 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002246 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002247 }
2248 else if (curproxy == NULL) {
2249 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002253
2254 /* update the current file and line being parsed */
2255 curproxy->conf.args.file = curproxy->conf.file;
2256 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002257
2258 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002259 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2260 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2261 if (err_code & ERR_FATAL)
2262 goto out;
2263 }
2264 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002265 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002266 int cur_arg;
2267
Willy Tarreaubaaee002006-06-26 02:48:02 +02002268 if (curproxy == &defproxy) {
2269 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002270 err_code |= ERR_ALERT | ERR_FATAL;
2271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002272 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002273 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002274 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002275
Willy Tarreau24709282013-03-10 21:32:12 +01002276 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002277 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002279 err_code |= ERR_ALERT | ERR_FATAL;
2280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002281 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002282
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002283 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002284
2285 /* use default settings for unix sockets */
2286 bind_conf->ux.uid = global.unix_bind.ux.uid;
2287 bind_conf->ux.gid = global.unix_bind.ux.gid;
2288 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002289
2290 /* NOTE: the following line might create several listeners if there
2291 * are comma-separated IPs or port ranges. So all further processing
2292 * will have to be applied to all listeners created after last_listen.
2293 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002294 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2295 if (errmsg && *errmsg) {
2296 indent_msg(&errmsg, 2);
2297 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002298 }
2299 else
2300 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2301 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002302 err_code |= ERR_ALERT | ERR_FATAL;
2303 goto out;
2304 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002305
Willy Tarreau4348fad2012-09-20 16:48:07 +02002306 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2307 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002308 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002309 }
2310
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002311 cur_arg = 2;
2312 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002313 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002314 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002315 char *err;
2316
Willy Tarreau26982662012-09-12 23:17:10 +02002317 kw = bind_find_kw(args[cur_arg]);
2318 if (kw) {
2319 char *err = NULL;
2320 int code;
2321
2322 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002323 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2324 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002325 cur_arg += 1 + kw->skip ;
2326 err_code |= ERR_ALERT | ERR_FATAL;
2327 goto out;
2328 }
2329
Willy Tarreau4348fad2012-09-20 16:48:07 +02002330 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002331 err_code |= code;
2332
2333 if (code) {
2334 if (err && *err) {
2335 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002336 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002337 }
2338 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002339 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2340 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002341 if (code & ERR_FATAL) {
2342 free(err);
2343 cur_arg += 1 + kw->skip;
2344 goto out;
2345 }
2346 }
2347 free(err);
2348 cur_arg += 1 + kw->skip;
2349 continue;
2350 }
2351
Willy Tarreau8638f482012-09-18 18:01:17 +02002352 err = NULL;
2353 if (!bind_dumped) {
2354 bind_dump_kws(&err);
2355 indent_msg(&err, 4);
2356 bind_dumped = 1;
2357 }
2358
2359 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2360 file, linenum, args[0], args[1], args[cur_arg],
2361 err ? " Registered keywords :" : "", err ? err : "");
2362 free(err);
2363
Willy Tarreau93893792009-07-23 13:19:11 +02002364 err_code |= ERR_ALERT | ERR_FATAL;
2365 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002366 }
Willy Tarreau93893792009-07-23 13:19:11 +02002367 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002368 }
2369 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002370 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002371 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2372 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002373 err_code |= ERR_ALERT | ERR_FATAL;
2374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002375 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002377 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378
Willy Tarreaubaaee002006-06-26 02:48:02 +02002379 /* flush useless bits */
2380 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002383 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002384 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002385 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002386
Willy Tarreau1c47f852006-07-09 08:22:27 +02002387 if (!*args[1]) {
2388 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2389 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002392 }
2393
Willy Tarreaua534fea2008-08-03 12:19:50 +02002394 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002395 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002396 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002397 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002398 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2399
Willy Tarreau93893792009-07-23 13:19:11 +02002400 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2403 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2404 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2405 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2406 else {
2407 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002408 err_code |= ERR_ALERT | ERR_FATAL;
2409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002410 }
2411 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002412 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002413 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002414
2415 if (curproxy == &defproxy) {
2416 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002420 }
2421
2422 if (!*args[1]) {
2423 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2424 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002427 }
2428
2429 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002430 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002431
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002432 if (curproxy->uuid <= 0) {
2433 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002434 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002437 }
2438
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002439 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2440 if (node) {
2441 struct proxy *target = container_of(node, struct proxy, conf.id);
2442 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2443 file, linenum, proxy_type_str(curproxy), curproxy->id,
2444 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
2447 }
2448 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002449 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002450 else if (!strcmp(args[0], "description")) {
2451 int i, len=0;
2452 char *d;
2453
Cyril Bonté99ed3272010-01-24 23:29:44 +01002454 if (curproxy == &defproxy) {
2455 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2456 file, linenum, args[0]);
2457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
2459 }
2460
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002461 if (!*args[1]) {
2462 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2463 file, linenum, args[0]);
2464 return -1;
2465 }
2466
Willy Tarreau348acfe2014-04-14 15:00:39 +02002467 for (i = 1; *args[i]; i++)
2468 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002469
2470 d = (char *)calloc(1, len);
2471 curproxy->desc = d;
2472
Willy Tarreau348acfe2014-04-14 15:00:39 +02002473 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2474 for (i = 2; *args[i]; i++)
2475 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002476
2477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002478 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2479 curproxy->state = PR_STSTOPPED;
2480 }
2481 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2482 curproxy->state = PR_STNEW;
2483 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002484 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2485 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002486 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002487
2488 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002489 unsigned int low, high;
2490
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002491 if (strcmp(args[cur_arg], "all") == 0) {
2492 set = 0;
2493 break;
2494 }
2495 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002496 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002497 }
2498 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002499 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002500 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002501 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002502 char *dash = strchr(args[cur_arg], '-');
2503
2504 low = high = str2uic(args[cur_arg]);
2505 if (dash)
2506 high = str2uic(dash + 1);
2507
2508 if (high < low) {
2509 unsigned int swap = low;
2510 low = high;
2511 high = swap;
2512 }
2513
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002514 if (low < 1 || high > LONGBITS) {
2515 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2516 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002517 err_code |= ERR_ALERT | ERR_FATAL;
2518 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002519 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002520 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002521 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002522 }
2523 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002524 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2525 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002528 }
2529 cur_arg++;
2530 }
2531 curproxy->bind_proc = set;
2532 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002533 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002534 if (curproxy == &defproxy) {
2535 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002536 err_code |= ERR_ALERT | ERR_FATAL;
2537 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002538 }
2539
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002540 err = invalid_char(args[1]);
2541 if (err) {
2542 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2543 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002544 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002545 }
2546
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002547 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002548 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2549 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002552 }
2553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2555 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002559
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 if (*(args[1]) == 0) {
2561 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2562 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_ALERT | ERR_FATAL;
2564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002565 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002566
Willy Tarreau67402132012-05-31 20:40:20 +02002567 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002568 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002569 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002570 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 curproxy->cookie_name = strdup(args[1]);
2572 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002573
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 cur_arg = 2;
2575 while (*(args[cur_arg])) {
2576 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002577 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002578 }
2579 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002580 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002581 }
2582 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002583 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002584 }
2585 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002586 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
2588 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002589 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002590 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002591 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002592 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002593 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002595 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002597 else if (!strcmp(args[cur_arg], "httponly")) {
2598 curproxy->ck_opts |= PR_CK_HTTPONLY;
2599 }
2600 else if (!strcmp(args[cur_arg], "secure")) {
2601 curproxy->ck_opts |= PR_CK_SECURE;
2602 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002603 else if (!strcmp(args[cur_arg], "domain")) {
2604 if (!*args[cur_arg + 1]) {
2605 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2606 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002607 err_code |= ERR_ALERT | ERR_FATAL;
2608 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002609 }
2610
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002611 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002612 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002613 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2614 " dots nor does not start with a dot."
2615 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002616 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002617 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002618 }
2619
2620 err = invalid_domainchar(args[cur_arg + 1]);
2621 if (err) {
2622 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2623 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002624 err_code |= ERR_ALERT | ERR_FATAL;
2625 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002626 }
2627
Willy Tarreau68a897b2009-12-03 23:28:34 +01002628 if (!curproxy->cookie_domain) {
2629 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2630 } else {
2631 /* one domain was already specified, add another one by
2632 * building the string which will be returned along with
2633 * the cookie.
2634 */
2635 char *new_ptr;
2636 int new_len = strlen(curproxy->cookie_domain) +
2637 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2638 new_ptr = malloc(new_len);
2639 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2640 free(curproxy->cookie_domain);
2641 curproxy->cookie_domain = new_ptr;
2642 }
Willy Tarreau31936852010-10-06 16:59:56 +02002643 cur_arg++;
2644 }
2645 else if (!strcmp(args[cur_arg], "maxidle")) {
2646 unsigned int maxidle;
2647 const char *res;
2648
2649 if (!*args[cur_arg + 1]) {
2650 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2651 file, linenum, args[cur_arg]);
2652 err_code |= ERR_ALERT | ERR_FATAL;
2653 goto out;
2654 }
2655
2656 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2657 if (res) {
2658 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2659 file, linenum, *res, args[cur_arg]);
2660 err_code |= ERR_ALERT | ERR_FATAL;
2661 goto out;
2662 }
2663 curproxy->cookie_maxidle = maxidle;
2664 cur_arg++;
2665 }
2666 else if (!strcmp(args[cur_arg], "maxlife")) {
2667 unsigned int maxlife;
2668 const char *res;
2669
2670 if (!*args[cur_arg + 1]) {
2671 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2672 file, linenum, args[cur_arg]);
2673 err_code |= ERR_ALERT | ERR_FATAL;
2674 goto out;
2675 }
2676
2677 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2678 if (res) {
2679 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2680 file, linenum, *res, args[cur_arg]);
2681 err_code |= ERR_ALERT | ERR_FATAL;
2682 goto out;
2683 }
2684 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002685 cur_arg++;
2686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002688 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 +02002689 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002690 err_code |= ERR_ALERT | ERR_FATAL;
2691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }
2693 cur_arg++;
2694 }
Willy Tarreau67402132012-05-31 20:40:20 +02002695 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002696 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2697 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002698 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002699 }
2700
Willy Tarreau67402132012-05-31 20:40:20 +02002701 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2703 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002704 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002705 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002706
Willy Tarreau67402132012-05-31 20:40:20 +02002707 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002708 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2709 file, linenum);
2710 err_code |= ERR_ALERT | ERR_FATAL;
2711 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002713 else if (!strcmp(args[0], "external-check")) {
2714 if (*(args[1]) == 0) {
2715 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2716 file, linenum, args[0]);
2717 err_code |= ERR_ALERT | ERR_FATAL;
2718 goto out;
2719 }
2720
2721 if (!strcmp(args[1], "command")) {
2722 if (*(args[1]) == 0) {
2723 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2724 file, linenum, args[1]);
2725 err_code |= ERR_ALERT | ERR_FATAL;
2726 goto out;
2727 }
2728 free(curproxy->check_command);
2729 curproxy->check_command = strdup(args[2]);
2730 }
2731 else if (!strcmp(args[1], "path")) {
2732 if (*(args[1]) == 0) {
2733 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2734 file, linenum, args[1]);
2735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
2737 }
2738 free(curproxy->check_path);
2739 curproxy->check_path = strdup(args[2]);
2740 }
2741 else {
2742 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2743 file, linenum, args[1]);
2744 err_code |= ERR_ALERT | ERR_FATAL;
2745 goto out;
2746 }
2747 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002748 else if (!strcmp(args[0], "persist")) { /* persist */
2749 if (*(args[1]) == 0) {
2750 Alert("parsing [%s:%d] : missing persist method.\n",
2751 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002752 err_code |= ERR_ALERT | ERR_FATAL;
2753 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002754 }
2755
2756 if (!strncmp(args[1], "rdp-cookie", 10)) {
2757 curproxy->options2 |= PR_O2_RDPC_PRST;
2758
Emeric Brunb982a3d2010-01-04 15:45:53 +01002759 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002760 const char *beg, *end;
2761
2762 beg = args[1] + 11;
2763 end = strchr(beg, ')');
2764
2765 if (!end || end == beg) {
2766 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2767 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_ALERT | ERR_FATAL;
2769 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002770 }
2771
2772 free(curproxy->rdp_cookie_name);
2773 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2774 curproxy->rdp_cookie_len = end-beg;
2775 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002776 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002777 free(curproxy->rdp_cookie_name);
2778 curproxy->rdp_cookie_name = strdup("msts");
2779 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2780 }
2781 else { /* syntax */
2782 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2783 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002786 }
2787 }
2788 else {
2789 Alert("parsing [%s:%d] : unknown persist method.\n",
2790 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002793 }
2794 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002795 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002796 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002798 if (curproxy == &defproxy) {
2799 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
2802 }
2803
Willy Tarreau977b8e42006-12-29 14:19:17 +01002804 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002805 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002806
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002808 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002809 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002810 err_code |= ERR_ALERT | ERR_FATAL;
2811 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002812 }
2813 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002814 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 curproxy->appsession_name = strdup(args[1]);
2816 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2817 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002818 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2819 if (err) {
2820 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2821 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002824 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002825 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002826
Willy Tarreau51041c72007-09-09 21:56:53 +02002827 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2828 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_ABORT;
2830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002832
2833 cur_arg = 6;
2834 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002835 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2836 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002837 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002838 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002839 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002840 } else if (!strcmp(args[cur_arg], "prefix")) {
2841 curproxy->options2 |= PR_O2_AS_PFX;
2842 } else if (!strcmp(args[cur_arg], "mode")) {
2843 if (!*args[cur_arg + 1]) {
2844 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2845 file, linenum, args[0], args[cur_arg]);
2846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
2848 }
2849
2850 cur_arg++;
2851 if (!strcmp(args[cur_arg], "query-string")) {
2852 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2853 curproxy->options2 |= PR_O2_AS_M_QS;
2854 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2855 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2856 curproxy->options2 |= PR_O2_AS_M_PP;
2857 } else {
2858 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002863 cur_arg++;
2864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 } /* Url App Session */
2866 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002867 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002869
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002871 if (curproxy == &defproxy) {
2872 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 if (*(args[4]) == 0) {
2878 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2879 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002880 err_code |= ERR_ALERT | ERR_FATAL;
2881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002883 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 curproxy->capture_name = strdup(args[2]);
2885 curproxy->capture_namelen = strlen(curproxy->capture_name);
2886 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 curproxy->to_log |= LW_COOKIE;
2888 }
2889 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2890 struct cap_hdr *hdr;
2891
2892 if (curproxy == &defproxy) {
2893 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 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
2897
2898 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2899 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2900 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002901 err_code |= ERR_ALERT | ERR_FATAL;
2902 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 }
2904
2905 hdr = calloc(sizeof(struct cap_hdr), 1);
2906 hdr->next = curproxy->req_cap;
2907 hdr->name = strdup(args[3]);
2908 hdr->namelen = strlen(args[3]);
2909 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002910 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002911 hdr->index = curproxy->nb_req_cap++;
2912 curproxy->req_cap = hdr;
2913 curproxy->to_log |= LW_REQHDR;
2914 }
2915 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2916 struct cap_hdr *hdr;
2917
2918 if (curproxy == &defproxy) {
2919 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 +02002920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002922 }
2923
2924 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2925 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2926 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929 }
2930 hdr = calloc(sizeof(struct cap_hdr), 1);
2931 hdr->next = curproxy->rsp_cap;
2932 hdr->name = strdup(args[3]);
2933 hdr->namelen = strlen(args[3]);
2934 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002935 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002936 hdr->index = curproxy->nb_rsp_cap++;
2937 curproxy->rsp_cap = hdr;
2938 curproxy->to_log |= LW_RSPHDR;
2939 }
2940 else {
2941 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 }
2946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002947 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002948 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002949 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002950
Willy Tarreaubaaee002006-06-26 02:48:02 +02002951 if (*(args[1]) == 0) {
2952 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002954 err_code |= ERR_ALERT | ERR_FATAL;
2955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 }
2957 curproxy->conn_retries = atol(args[1]);
2958 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002959 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002960 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002961
2962 if (curproxy == &defproxy) {
2963 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
2966 }
2967
Willy Tarreau20b0de52012-12-24 15:45:22 +01002968 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2969 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2970 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2971 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002972 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002973 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2974 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 +01002975 file, linenum, args[0]);
2976 err_code |= ERR_WARN;
2977 }
2978
Willy Tarreauff011f22011-01-06 17:51:27 +01002979 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002980
Willy Tarreauff011f22011-01-06 17:51:27 +01002981 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002982 err_code |= ERR_ALERT | ERR_ABORT;
2983 goto out;
2984 }
2985
Willy Tarreau5002f572014-04-23 01:32:02 +02002986 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002987 err_code |= warnif_cond_conflicts(rule->cond,
2988 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2989 file, linenum);
2990
Willy Tarreauff011f22011-01-06 17:51:27 +01002991 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002992 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002993 else if (!strcmp(args[0], "http-response")) { /* response access control */
2994 struct http_res_rule *rule;
2995
2996 if (curproxy == &defproxy) {
2997 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2998 err_code |= ERR_ALERT | ERR_FATAL;
2999 goto out;
3000 }
3001
3002 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3003 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3004 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3005 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3006 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3007 file, linenum, args[0]);
3008 err_code |= ERR_WARN;
3009 }
3010
3011 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3012
3013 if (!rule) {
3014 err_code |= ERR_ALERT | ERR_ABORT;
3015 goto out;
3016 }
3017
3018 err_code |= warnif_cond_conflicts(rule->cond,
3019 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3020 file, linenum);
3021
3022 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3023 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003024 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3025 /* set the header name and length into the proxy structure */
3026 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3027 err_code |= ERR_WARN;
3028
3029 if (!*args[1]) {
3030 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3031 file, linenum, args[0]);
3032 err_code |= ERR_ALERT | ERR_FATAL;
3033 goto out;
3034 }
3035
3036 /* set the desired header name */
3037 free(curproxy->server_id_hdr_name);
3038 curproxy->server_id_hdr_name = strdup(args[1]);
3039 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3040 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003041 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003042 struct http_req_rule *rule;
3043
Willy Tarreaub099aca2008-10-12 17:26:37 +02003044 if (curproxy == &defproxy) {
3045 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_ALERT | ERR_FATAL;
3047 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003048 }
3049
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003050 /* emulate "block" using "http-request block". Since these rules are supposed to
3051 * be processed before all http-request rules, we put them into their own list
3052 * and will insert them at the end.
3053 */
3054 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3055 if (!rule) {
3056 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003057 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003058 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003059 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3060 err_code |= warnif_cond_conflicts(rule->cond,
3061 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3062 file, linenum);
3063 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003064
3065 if (!already_warned(WARN_BLOCK_DEPRECATED))
3066 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]);
3067
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003068 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003069 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003070 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003071
Cyril Bonté99ed3272010-01-24 23:29:44 +01003072 if (curproxy == &defproxy) {
3073 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3074 err_code |= ERR_ALERT | ERR_FATAL;
3075 goto out;
3076 }
3077
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003078 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003079 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3080 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003083 }
3084
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003085 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003086 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003087 err_code |= warnif_cond_conflicts(rule->cond,
3088 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3089 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003090 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003091 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003092 struct switching_rule *rule;
3093
Willy Tarreaub099aca2008-10-12 17:26:37 +02003094 if (curproxy == &defproxy) {
3095 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003098 }
3099
Willy Tarreau55ea7572007-06-17 19:56:27 +02003100 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003102
3103 if (*(args[1]) == 0) {
3104 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003107 }
3108
Willy Tarreauf51658d2014-04-23 01:21:56 +02003109 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3110 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3111 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3112 file, linenum, errmsg);
3113 err_code |= ERR_ALERT | ERR_FATAL;
3114 goto out;
3115 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003116
Willy Tarreauf51658d2014-04-23 01:21:56 +02003117 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003118 }
3119
3120 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3121 rule->cond = cond;
3122 rule->be.name = strdup(args[1]);
3123 LIST_INIT(&rule->list);
3124 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3125 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003126 else if (strcmp(args[0], "use-server") == 0) {
3127 struct server_rule *rule;
3128
3129 if (curproxy == &defproxy) {
3130 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
3133 }
3134
3135 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3136 err_code |= ERR_WARN;
3137
3138 if (*(args[1]) == 0) {
3139 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
3142 }
3143
3144 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3145 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3146 file, linenum, args[0]);
3147 err_code |= ERR_ALERT | ERR_FATAL;
3148 goto out;
3149 }
3150
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003151 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3152 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3153 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003154 err_code |= ERR_ALERT | ERR_FATAL;
3155 goto out;
3156 }
3157
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003158 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003159
3160 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3161 rule->cond = cond;
3162 rule->srv.name = strdup(args[1]);
3163 LIST_INIT(&rule->list);
3164 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3165 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3166 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003167 else if ((!strcmp(args[0], "force-persist")) ||
3168 (!strcmp(args[0], "ignore-persist"))) {
3169 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003170
3171 if (curproxy == &defproxy) {
3172 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
3176
3177 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3178 err_code |= ERR_WARN;
3179
Willy Tarreauef6494c2010-01-28 17:12:36 +01003180 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003181 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3182 file, linenum, args[0]);
3183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
3185 }
3186
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003187 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3188 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3189 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
3192 }
3193
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003194 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3195 * where force-persist is applied.
3196 */
3197 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003198
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003199 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003200 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003201 if (!strcmp(args[0], "force-persist")) {
3202 rule->type = PERSIST_TYPE_FORCE;
3203 } else {
3204 rule->type = PERSIST_TYPE_IGNORE;
3205 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003206 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003207 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003208 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003209 else if (!strcmp(args[0], "stick-table")) {
3210 int myidx = 1;
3211
Emeric Brun32da3c42010-09-23 18:39:19 +02003212 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003213 curproxy->table.type = (unsigned int)-1;
3214 while (*args[myidx]) {
3215 const char *err;
3216
3217 if (strcmp(args[myidx], "size") == 0) {
3218 myidx++;
3219 if (!*(args[myidx])) {
3220 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3221 file, linenum, args[myidx-1]);
3222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
3225 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3226 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3227 file, linenum, *err, args[myidx-1]);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003231 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003232 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003233 else if (strcmp(args[myidx], "peers") == 0) {
3234 myidx++;
Godbach50523162013-12-11 19:48:57 +08003235 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003236 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3237 file, linenum, args[myidx-1]);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
Godbach50523162013-12-11 19:48:57 +08003240 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003241 curproxy->table.peers.name = strdup(args[myidx++]);
3242 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003243 else if (strcmp(args[myidx], "expire") == 0) {
3244 myidx++;
3245 if (!*(args[myidx])) {
3246 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3247 file, linenum, args[myidx-1]);
3248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
3250 }
3251 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3252 if (err) {
3253 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3254 file, linenum, *err, args[myidx-1]);
3255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
3257 }
3258 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003259 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003260 }
3261 else if (strcmp(args[myidx], "nopurge") == 0) {
3262 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003263 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003264 }
3265 else if (strcmp(args[myidx], "type") == 0) {
3266 myidx++;
3267 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3268 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3269 file, linenum, args[myidx]);
3270 err_code |= ERR_ALERT | ERR_FATAL;
3271 goto out;
3272 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003273 /* myidx already points to next arg */
3274 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003275 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003276 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003277 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003278
3279 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003280 nw = args[myidx];
3281 while (*nw) {
3282 /* the "store" keyword supports a comma-separated list */
3283 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003284 sa = NULL; /* store arg */
3285 while (*nw && *nw != ',') {
3286 if (*nw == '(') {
3287 *nw = 0;
3288 sa = ++nw;
3289 while (*nw != ')') {
3290 if (!*nw) {
3291 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3292 file, linenum, args[0], cw);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295 }
3296 nw++;
3297 }
3298 *nw = '\0';
3299 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003300 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003301 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003302 if (*nw)
3303 *nw++ = '\0';
3304 type = stktable_get_data_type(cw);
3305 if (type < 0) {
3306 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3307 file, linenum, args[0], cw);
3308 err_code |= ERR_ALERT | ERR_FATAL;
3309 goto out;
3310 }
Willy Tarreauac782882010-06-20 10:41:54 +02003311
3312 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3313 switch (err) {
3314 case PE_NONE: break;
3315 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003316 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3317 file, linenum, args[0], cw);
3318 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003319 break;
3320
3321 case PE_ARG_MISSING:
3322 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3323 file, linenum, args[0], cw);
3324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
3326
3327 case PE_ARG_NOT_USED:
3328 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3329 file, linenum, args[0], cw);
3330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
3332
3333 default:
3334 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3335 file, linenum, args[0], cw);
3336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003338 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003339 }
3340 myidx++;
3341 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003342 else {
3343 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3344 file, linenum, args[myidx]);
3345 err_code |= ERR_ALERT | ERR_FATAL;
3346 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003347 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003348 }
3349
3350 if (!curproxy->table.size) {
3351 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3352 file, linenum);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
3357 if (curproxy->table.type == (unsigned int)-1) {
3358 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3359 file, linenum);
3360 err_code |= ERR_ALERT | ERR_FATAL;
3361 goto out;
3362 }
3363 }
3364 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003365 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003366 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003367 int myidx = 0;
3368 const char *name = NULL;
3369 int flags;
3370
3371 if (curproxy == &defproxy) {
3372 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
3376
3377 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3378 err_code |= ERR_WARN;
3379 goto out;
3380 }
3381
3382 myidx++;
3383 if ((strcmp(args[myidx], "store") == 0) ||
3384 (strcmp(args[myidx], "store-request") == 0)) {
3385 myidx++;
3386 flags = STK_IS_STORE;
3387 }
3388 else if (strcmp(args[myidx], "store-response") == 0) {
3389 myidx++;
3390 flags = STK_IS_STORE | STK_ON_RSP;
3391 }
3392 else if (strcmp(args[myidx], "match") == 0) {
3393 myidx++;
3394 flags = STK_IS_MATCH;
3395 }
3396 else if (strcmp(args[myidx], "on") == 0) {
3397 myidx++;
3398 flags = STK_IS_MATCH | STK_IS_STORE;
3399 }
3400 else {
3401 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405
3406 if (*(args[myidx]) == 0) {
3407 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3408 err_code |= ERR_ALERT | ERR_FATAL;
3409 goto out;
3410 }
3411
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003412 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003413 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003414 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003415 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
3420 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003421 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3422 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3423 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003424 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003425 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003426 goto out;
3427 }
3428 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003429 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3430 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3431 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003432 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003433 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003434 goto out;
3435 }
3436 }
3437
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003438 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003439 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003440
Emeric Brunb982a3d2010-01-04 15:45:53 +01003441 if (strcmp(args[myidx], "table") == 0) {
3442 myidx++;
3443 name = args[myidx++];
3444 }
3445
Willy Tarreauef6494c2010-01-28 17:12:36 +01003446 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003447 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3448 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3449 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003450 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003451 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003452 goto out;
3453 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003454 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003455 else if (*(args[myidx])) {
3456 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3457 file, linenum, args[0], args[myidx]);
3458 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003459 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003460 goto out;
3461 }
Emeric Brun97679e72010-09-23 17:56:44 +02003462 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003463 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003464 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003465 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003466
Emeric Brunb982a3d2010-01-04 15:45:53 +01003467 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3468 rule->cond = cond;
3469 rule->expr = expr;
3470 rule->flags = flags;
3471 rule->table.name = name ? strdup(name) : NULL;
3472 LIST_INIT(&rule->list);
3473 if (flags & STK_ON_RSP)
3474 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3475 else
3476 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003478 else if (!strcmp(args[0], "stats")) {
3479 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3480 curproxy->uri_auth = NULL; /* we must detach from the default config */
3481
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003482 if (!*args[1]) {
3483 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003484 } else if (!strcmp(args[1], "admin")) {
3485 struct stats_admin_rule *rule;
3486
3487 if (curproxy == &defproxy) {
3488 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
3491 }
3492
3493 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3494 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3495 err_code |= ERR_ALERT | ERR_ABORT;
3496 goto out;
3497 }
3498
3499 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3500 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3501 file, linenum, args[0], args[1]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003505 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3506 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3507 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003508 err_code |= ERR_ALERT | ERR_FATAL;
3509 goto out;
3510 }
3511
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003512 err_code |= warnif_cond_conflicts(cond,
3513 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3514 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003515
3516 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3517 rule->cond = cond;
3518 LIST_INIT(&rule->list);
3519 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003520 } else if (!strcmp(args[1], "uri")) {
3521 if (*(args[2]) == 0) {
3522 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3526 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003527 err_code |= ERR_ALERT | ERR_ABORT;
3528 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003529 }
3530 } else if (!strcmp(args[1], "realm")) {
3531 if (*(args[2]) == 0) {
3532 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003533 err_code |= ERR_ALERT | ERR_FATAL;
3534 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003535 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3536 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_ABORT;
3538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003540 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003541 unsigned interval;
3542
3543 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3544 if (err) {
3545 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3546 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003549 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3550 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_ABORT;
3552 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003553 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003554 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003555 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003556
3557 if (curproxy == &defproxy) {
3558 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
3561 }
3562
3563 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3564 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3565 err_code |= ERR_ALERT | ERR_ABORT;
3566 goto out;
3567 }
3568
Willy Tarreauff011f22011-01-06 17:51:27 +01003569 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3570 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003571 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3572 file, linenum, args[0]);
3573 err_code |= ERR_WARN;
3574 }
3575
Willy Tarreauff011f22011-01-06 17:51:27 +01003576 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003577
Willy Tarreauff011f22011-01-06 17:51:27 +01003578 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003579 err_code |= ERR_ALERT | ERR_ABORT;
3580 goto out;
3581 }
3582
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003583 err_code |= warnif_cond_conflicts(rule->cond,
3584 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3585 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003586 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003587
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 } else if (!strcmp(args[1], "auth")) {
3589 if (*(args[2]) == 0) {
3590 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003591 err_code |= ERR_ALERT | ERR_FATAL;
3592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3594 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_ALERT | ERR_ABORT;
3596 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 }
3598 } else if (!strcmp(args[1], "scope")) {
3599 if (*(args[2]) == 0) {
3600 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003603 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3604 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003605 err_code |= ERR_ALERT | ERR_ABORT;
3606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 }
3608 } else if (!strcmp(args[1], "enable")) {
3609 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3610 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_ABORT;
3612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003614 } else if (!strcmp(args[1], "hide-version")) {
3615 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3616 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003617 err_code |= ERR_ALERT | ERR_ABORT;
3618 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003619 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003620 } else if (!strcmp(args[1], "show-legends")) {
3621 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3622 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3623 err_code |= ERR_ALERT | ERR_ABORT;
3624 goto out;
3625 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003626 } else if (!strcmp(args[1], "show-node")) {
3627
3628 if (*args[2]) {
3629 int i;
3630 char c;
3631
3632 for (i=0; args[2][i]; i++) {
3633 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003634 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3635 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003636 break;
3637 }
3638
3639 if (!i || args[2][i]) {
3640 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3641 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3642 file, linenum, args[0], args[1]);
3643 err_code |= ERR_ALERT | ERR_FATAL;
3644 goto out;
3645 }
3646 }
3647
3648 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3649 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3650 err_code |= ERR_ALERT | ERR_ABORT;
3651 goto out;
3652 }
3653 } else if (!strcmp(args[1], "show-desc")) {
3654 char *desc = NULL;
3655
3656 if (*args[2]) {
3657 int i, len=0;
3658 char *d;
3659
Willy Tarreau348acfe2014-04-14 15:00:39 +02003660 for (i = 2; *args[i]; i++)
3661 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003662
3663 desc = d = (char *)calloc(1, len);
3664
Willy Tarreau348acfe2014-04-14 15:00:39 +02003665 d += snprintf(d, desc + len - d, "%s", args[2]);
3666 for (i = 3; *args[i]; i++)
3667 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003668 }
3669
3670 if (!*args[2] && !global.desc)
3671 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3672 file, linenum, args[1]);
3673 else {
3674 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3675 free(desc);
3676 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3677 err_code |= ERR_ALERT | ERR_ABORT;
3678 goto out;
3679 }
3680 free(desc);
3681 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003682 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003683stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003684 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 +01003685 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003686 err_code |= ERR_ALERT | ERR_FATAL;
3687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003688 }
3689 }
3690 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003691 int optnum;
3692
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003693 if (*(args[1]) == '\0') {
3694 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3695 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003698 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003699
3700 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3701 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003702 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3703 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3704 file, linenum, cfg_opts[optnum].name);
3705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
3707 }
Willy Tarreau93893792009-07-23 13:19:11 +02003708 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3709 err_code |= ERR_WARN;
3710 goto out;
3711 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003712
Willy Tarreau3842f002009-06-14 11:39:52 +02003713 curproxy->no_options &= ~cfg_opts[optnum].val;
3714 curproxy->options &= ~cfg_opts[optnum].val;
3715
3716 switch (kwm) {
3717 case KWM_STD:
3718 curproxy->options |= cfg_opts[optnum].val;
3719 break;
3720 case KWM_NO:
3721 curproxy->no_options |= cfg_opts[optnum].val;
3722 break;
3723 case KWM_DEF: /* already cleared */
3724 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003725 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003726
Willy Tarreau93893792009-07-23 13:19:11 +02003727 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003728 }
3729 }
3730
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003731 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3732 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003733 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3734 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3735 file, linenum, cfg_opts2[optnum].name);
3736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
3738 }
Willy Tarreau93893792009-07-23 13:19:11 +02003739 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3740 err_code |= ERR_WARN;
3741 goto out;
3742 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003743
Willy Tarreau3842f002009-06-14 11:39:52 +02003744 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3745 curproxy->options2 &= ~cfg_opts2[optnum].val;
3746
3747 switch (kwm) {
3748 case KWM_STD:
3749 curproxy->options2 |= cfg_opts2[optnum].val;
3750 break;
3751 case KWM_NO:
3752 curproxy->no_options2 |= cfg_opts2[optnum].val;
3753 break;
3754 case KWM_DEF: /* already cleared */
3755 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003756 }
Willy Tarreau93893792009-07-23 13:19:11 +02003757 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003758 }
3759 }
3760
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003761 /* HTTP options override each other. They can be cancelled using
3762 * "no option xxx" which only switches to default mode if the mode
3763 * was this one (useful for cancelling options set in defaults
3764 * sections).
3765 */
3766 if (strcmp(args[1], "httpclose") == 0) {
3767 if (kwm == KWM_STD) {
3768 curproxy->options &= ~PR_O_HTTP_MODE;
3769 curproxy->options |= PR_O_HTTP_PCL;
3770 goto out;
3771 }
3772 else if (kwm == KWM_NO) {
3773 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3774 curproxy->options &= ~PR_O_HTTP_MODE;
3775 goto out;
3776 }
3777 }
3778 else if (strcmp(args[1], "forceclose") == 0) {
3779 if (kwm == KWM_STD) {
3780 curproxy->options &= ~PR_O_HTTP_MODE;
3781 curproxy->options |= PR_O_HTTP_FCL;
3782 goto out;
3783 }
3784 else if (kwm == KWM_NO) {
3785 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3786 curproxy->options &= ~PR_O_HTTP_MODE;
3787 goto out;
3788 }
3789 }
3790 else if (strcmp(args[1], "http-server-close") == 0) {
3791 if (kwm == KWM_STD) {
3792 curproxy->options &= ~PR_O_HTTP_MODE;
3793 curproxy->options |= PR_O_HTTP_SCL;
3794 goto out;
3795 }
3796 else if (kwm == KWM_NO) {
3797 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3798 curproxy->options &= ~PR_O_HTTP_MODE;
3799 goto out;
3800 }
3801 }
3802 else if (strcmp(args[1], "http-keep-alive") == 0) {
3803 if (kwm == KWM_STD) {
3804 curproxy->options &= ~PR_O_HTTP_MODE;
3805 curproxy->options |= PR_O_HTTP_KAL;
3806 goto out;
3807 }
3808 else if (kwm == KWM_NO) {
3809 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3810 curproxy->options &= ~PR_O_HTTP_MODE;
3811 goto out;
3812 }
3813 }
3814 else if (strcmp(args[1], "http-tunnel") == 0) {
3815 if (kwm == KWM_STD) {
3816 curproxy->options &= ~PR_O_HTTP_MODE;
3817 curproxy->options |= PR_O_HTTP_TUN;
3818 goto out;
3819 }
3820 else if (kwm == KWM_NO) {
3821 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3822 curproxy->options &= ~PR_O_HTTP_MODE;
3823 goto out;
3824 }
3825 }
3826
Willy Tarreau3842f002009-06-14 11:39:52 +02003827 if (kwm != KWM_STD) {
3828 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003829 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003832 }
3833
Emeric Brun3a058f32009-06-30 18:26:00 +02003834 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003835 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003837 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003838 if (*(args[2]) != '\0') {
3839 if (!strcmp(args[2], "clf")) {
3840 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003841 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003842 } else {
3843 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003846 }
3847 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003848 if (curproxy->conf.logformat_string != default_http_log_format &&
3849 curproxy->conf.logformat_string != default_tcp_log_format &&
3850 curproxy->conf.logformat_string != clf_http_log_format)
3851 free(curproxy->conf.logformat_string);
3852 curproxy->conf.logformat_string = logformat;
3853
3854 free(curproxy->conf.lfs_file);
3855 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3856 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003857 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003858 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003859 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003860 if (curproxy->conf.logformat_string != default_http_log_format &&
3861 curproxy->conf.logformat_string != default_tcp_log_format &&
3862 curproxy->conf.logformat_string != clf_http_log_format)
3863 free(curproxy->conf.logformat_string);
3864 curproxy->conf.logformat_string = default_tcp_log_format;
3865
3866 free(curproxy->conf.lfs_file);
3867 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3868 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003869 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003870 else if (!strcmp(args[1], "tcpka")) {
3871 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003872 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003873 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003874
3875 if (curproxy->cap & PR_CAP_FE)
3876 curproxy->options |= PR_O_TCP_CLI_KA;
3877 if (curproxy->cap & PR_CAP_BE)
3878 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 }
3880 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_WARN;
3883
Willy Tarreaubaaee002006-06-26 02:48:02 +02003884 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003885 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003886 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003887 curproxy->options2 &= ~PR_O2_CHK_ANY;
3888 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003889 if (!*args[2]) { /* no argument */
3890 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3891 curproxy->check_len = strlen(DEF_CHECK_REQ);
3892 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003893 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003894 curproxy->check_req = (char *)malloc(reqlen);
3895 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003896 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003897 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003898 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 if (*args[4])
3900 reqlen += strlen(args[4]);
3901 else
3902 reqlen += strlen("HTTP/1.0");
3903
3904 curproxy->check_req = (char *)malloc(reqlen);
3905 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003906 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003907 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003908 }
3909 else if (!strcmp(args[1], "ssl-hello-chk")) {
3910 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003912 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003913
Willy Tarreaua534fea2008-08-03 12:19:50 +02003914 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003915 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003916 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003917 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003918 }
Willy Tarreau23677902007-05-08 23:50:35 +02003919 else if (!strcmp(args[1], "smtpchk")) {
3920 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003921 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003922 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003923 curproxy->options2 &= ~PR_O2_CHK_ANY;
3924 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003925
3926 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3927 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3928 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3929 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3930 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3931 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3932 curproxy->check_req = (char *)malloc(reqlen);
3933 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3934 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3935 } else {
3936 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3937 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3938 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3939 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3940 }
3941 }
3942 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003943 else if (!strcmp(args[1], "pgsql-check")) {
3944 /* use PostgreSQL request to check servers' health */
3945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3946 err_code |= ERR_WARN;
3947
3948 free(curproxy->check_req);
3949 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003950 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003951 curproxy->options2 |= PR_O2_PGSQL_CHK;
3952
3953 if (*(args[2])) {
3954 int cur_arg = 2;
3955
3956 while (*(args[cur_arg])) {
3957 if (strcmp(args[cur_arg], "user") == 0) {
3958 char * packet;
3959 uint32_t packet_len;
3960 uint32_t pv;
3961
3962 /* suboption header - needs additional argument for it */
3963 if (*(args[cur_arg+1]) == 0) {
3964 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3965 file, linenum, args[0], args[1], args[cur_arg]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969
3970 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3971 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3972 pv = htonl(0x30000); /* protocol version 3.0 */
3973
3974 packet = (char*) calloc(1, packet_len);
3975
3976 memcpy(packet + 4, &pv, 4);
3977
3978 /* copy "user" */
3979 memcpy(packet + 8, "user", 4);
3980
3981 /* copy username */
3982 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3983
3984 free(curproxy->check_req);
3985 curproxy->check_req = packet;
3986 curproxy->check_len = packet_len;
3987
3988 packet_len = htonl(packet_len);
3989 memcpy(packet, &packet_len, 4);
3990 cur_arg += 2;
3991 } else {
3992 /* unknown suboption - catchall */
3993 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3994 file, linenum, args[0], args[1]);
3995 err_code |= ERR_ALERT | ERR_FATAL;
3996 goto out;
3997 }
3998 } /* end while loop */
3999 }
4000 }
4001
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004002 else if (!strcmp(args[1], "redis-check")) {
4003 /* use REDIS PING request to check servers' health */
4004 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4005 err_code |= ERR_WARN;
4006
4007 free(curproxy->check_req);
4008 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004009 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004010 curproxy->options2 |= PR_O2_REDIS_CHK;
4011
4012 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4013 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4014 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4015 }
4016
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004017 else if (!strcmp(args[1], "mysql-check")) {
4018 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004019 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4020 err_code |= ERR_WARN;
4021
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004022 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004023 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004024 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004025 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004026
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004027 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004028 * const char mysql40_client_auth_pkt[] = {
4029 * "\x0e\x00\x00" // packet length
4030 * "\x01" // packet number
4031 * "\x00\x00" // client capabilities
4032 * "\x00\x00\x01" // max packet
4033 * "haproxy\x00" // username (null terminated string)
4034 * "\x00" // filler (always 0x00)
4035 * "\x01\x00\x00" // packet length
4036 * "\x00" // packet number
4037 * "\x01" // COM_QUIT command
4038 * };
4039 */
4040
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004041 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4042 * const char mysql41_client_auth_pkt[] = {
4043 * "\x0e\x00\x00\" // packet length
4044 * "\x01" // packet number
4045 * "\x00\x00\x00\x00" // client capabilities
4046 * "\x00\x00\x00\x01" // max packet
4047 * "\x21" // character set (UTF-8)
4048 * char[23] // All zeroes
4049 * "haproxy\x00" // username (null terminated string)
4050 * "\x00" // filler (always 0x00)
4051 * "\x01\x00\x00" // packet length
4052 * "\x00" // packet number
4053 * "\x01" // COM_QUIT command
4054 * };
4055 */
4056
4057
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004058 if (*(args[2])) {
4059 int cur_arg = 2;
4060
4061 while (*(args[cur_arg])) {
4062 if (strcmp(args[cur_arg], "user") == 0) {
4063 char *mysqluser;
4064 int packetlen, reqlen, userlen;
4065
4066 /* suboption header - needs additional argument for it */
4067 if (*(args[cur_arg+1]) == 0) {
4068 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4069 file, linenum, args[0], args[1], args[cur_arg]);
4070 err_code |= ERR_ALERT | ERR_FATAL;
4071 goto out;
4072 }
4073 mysqluser = args[cur_arg + 1];
4074 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004075
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004076 if (*(args[cur_arg+2])) {
4077 if (!strcmp(args[cur_arg+2], "post-41")) {
4078 packetlen = userlen + 7 + 27;
4079 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004080
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004081 free(curproxy->check_req);
4082 curproxy->check_req = (char *)calloc(1, reqlen);
4083 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004084
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004085 snprintf(curproxy->check_req, 4, "%c%c%c",
4086 ((unsigned char) packetlen & 0xff),
4087 ((unsigned char) (packetlen >> 8) & 0xff),
4088 ((unsigned char) (packetlen >> 16) & 0xff));
4089
4090 curproxy->check_req[3] = 1;
4091 curproxy->check_req[5] = 130;
4092 curproxy->check_req[11] = 1;
4093 curproxy->check_req[12] = 33;
4094 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4095 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4096 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4097 cur_arg += 3;
4098 } else {
4099 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103 } else {
4104 packetlen = userlen + 7;
4105 reqlen = packetlen + 9;
4106
4107 free(curproxy->check_req);
4108 curproxy->check_req = (char *)calloc(1, reqlen);
4109 curproxy->check_len = reqlen;
4110
4111 snprintf(curproxy->check_req, 4, "%c%c%c",
4112 ((unsigned char) packetlen & 0xff),
4113 ((unsigned char) (packetlen >> 8) & 0xff),
4114 ((unsigned char) (packetlen >> 16) & 0xff));
4115
4116 curproxy->check_req[3] = 1;
4117 curproxy->check_req[5] = 128;
4118 curproxy->check_req[8] = 1;
4119 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4120 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4121 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4122 cur_arg += 2;
4123 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004124 } else {
4125 /* unknown suboption - catchall */
4126 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4127 file, linenum, args[0], args[1]);
4128 err_code |= ERR_ALERT | ERR_FATAL;
4129 goto out;
4130 }
4131 } /* end while loop */
4132 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004133 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004134 else if (!strcmp(args[1], "ldap-check")) {
4135 /* use LDAP request to check servers' health */
4136 free(curproxy->check_req);
4137 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004138 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004139 curproxy->options2 |= PR_O2_LDAP_CHK;
4140
4141 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4142 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4143 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4144 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004145 else if (!strcmp(args[1], "tcp-check")) {
4146 /* use raw TCPCHK send/expect to check servers' health */
4147 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4148 err_code |= ERR_WARN;
4149
4150 free(curproxy->check_req);
4151 curproxy->check_req = NULL;
4152 curproxy->options2 &= ~PR_O2_CHK_ANY;
4153 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4154 }
Simon Horman98637e52014-06-20 12:30:16 +09004155 else if (!strcmp(args[1], "external-check")) {
4156 /* excute an external command to check servers' health */
4157 free(curproxy->check_req);
4158 curproxy->check_req = NULL;
4159 curproxy->options2 &= ~PR_O2_CHK_ANY;
4160 curproxy->options2 |= PR_O2_EXT_CHK;
4161 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004162 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004163 int cur_arg;
4164
4165 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4166 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004167 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004168
Willy Tarreau87cf5142011-08-19 22:57:24 +02004169 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004170
4171 free(curproxy->fwdfor_hdr_name);
4172 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4173 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4174
4175 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4176 cur_arg = 2;
4177 while (*(args[cur_arg])) {
4178 if (!strcmp(args[cur_arg], "except")) {
4179 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004180 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004181 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4182 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004185 }
4186 /* flush useless bits */
4187 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004188 cur_arg += 2;
4189 } else if (!strcmp(args[cur_arg], "header")) {
4190 /* suboption header - needs additional argument for it */
4191 if (*(args[cur_arg+1]) == 0) {
4192 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4193 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004196 }
4197 free(curproxy->fwdfor_hdr_name);
4198 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4199 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4200 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004201 } else if (!strcmp(args[cur_arg], "if-none")) {
4202 curproxy->options &= ~PR_O_FF_ALWAYS;
4203 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004204 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004205 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004206 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004207 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004210 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004211 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004212 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004213 else if (!strcmp(args[1], "originalto")) {
4214 int cur_arg;
4215
4216 /* insert x-original-to field, but not for the IP address listed as an except.
4217 * set default options (ie: bitfield, header name, etc)
4218 */
4219
4220 curproxy->options |= PR_O_ORGTO;
4221
4222 free(curproxy->orgto_hdr_name);
4223 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4224 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4225
Willy Tarreau87cf5142011-08-19 22:57:24 +02004226 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004227 cur_arg = 2;
4228 while (*(args[cur_arg])) {
4229 if (!strcmp(args[cur_arg], "except")) {
4230 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004231 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 +02004232 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4233 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004236 }
4237 /* flush useless bits */
4238 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4239 cur_arg += 2;
4240 } else if (!strcmp(args[cur_arg], "header")) {
4241 /* suboption header - needs additional argument for it */
4242 if (*(args[cur_arg+1]) == 0) {
4243 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4244 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004245 err_code |= ERR_ALERT | ERR_FATAL;
4246 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004247 }
4248 free(curproxy->orgto_hdr_name);
4249 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4250 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4251 cur_arg += 2;
4252 } else {
4253 /* unknown suboption - catchall */
4254 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4255 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004256 err_code |= ERR_ALERT | ERR_FATAL;
4257 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004258 }
4259 } /* end while loop */
4260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 else {
4262 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004265 }
Willy Tarreau93893792009-07-23 13:19:11 +02004266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004267 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004268 else if (!strcmp(args[0], "default_backend")) {
4269 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004270 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004271
4272 if (*(args[1]) == 0) {
4273 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004274 err_code |= ERR_ALERT | ERR_FATAL;
4275 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004276 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004277 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004278 curproxy->defbe.name = strdup(args[1]);
4279 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004282 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004283
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004284 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4285 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 +01004286 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004287 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 /* enable reconnections to dispatch */
4289 curproxy->options |= PR_O_REDISP;
4290 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004291 else if (!strcmp(args[0], "http-check")) {
4292 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004293 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004294
4295 if (strcmp(args[1], "disable-on-404") == 0) {
4296 /* enable a graceful server shutdown on an HTTP 404 response */
4297 curproxy->options |= PR_O_DISABLE404;
4298 }
Willy Tarreauef781042010-01-27 11:53:01 +01004299 else if (strcmp(args[1], "send-state") == 0) {
4300 /* enable emission of the apparent state of a server in HTTP checks */
4301 curproxy->options2 |= PR_O2_CHK_SNDST;
4302 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004303 else if (strcmp(args[1], "expect") == 0) {
4304 const char *ptr_arg;
4305 int cur_arg;
4306
4307 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4308 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
4312
4313 cur_arg = 2;
4314 /* consider exclamation marks, sole or at the beginning of a word */
4315 while (*(ptr_arg = args[cur_arg])) {
4316 while (*ptr_arg == '!') {
4317 curproxy->options2 ^= PR_O2_EXP_INV;
4318 ptr_arg++;
4319 }
4320 if (*ptr_arg)
4321 break;
4322 cur_arg++;
4323 }
4324 /* now ptr_arg points to the beginning of a word past any possible
4325 * exclamation mark, and cur_arg is the argument which holds this word.
4326 */
4327 if (strcmp(ptr_arg, "status") == 0) {
4328 if (!*(args[cur_arg + 1])) {
4329 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4330 file, linenum, args[0], args[1], ptr_arg);
4331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
4333 }
4334 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004335 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004336 curproxy->expect_str = strdup(args[cur_arg + 1]);
4337 }
4338 else if (strcmp(ptr_arg, "string") == 0) {
4339 if (!*(args[cur_arg + 1])) {
4340 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4341 file, linenum, args[0], args[1], ptr_arg);
4342 err_code |= ERR_ALERT | ERR_FATAL;
4343 goto out;
4344 }
4345 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004346 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004347 curproxy->expect_str = strdup(args[cur_arg + 1]);
4348 }
4349 else if (strcmp(ptr_arg, "rstatus") == 0) {
4350 if (!*(args[cur_arg + 1])) {
4351 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4352 file, linenum, args[0], args[1], ptr_arg);
4353 err_code |= ERR_ALERT | ERR_FATAL;
4354 goto out;
4355 }
4356 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004357 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004358 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004359 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004360 free(curproxy->expect_regex);
4361 curproxy->expect_regex = NULL;
4362 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004363 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004364 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4365 error = NULL;
4366 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4367 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4368 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4369 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
4372 }
4373 }
4374 else if (strcmp(ptr_arg, "rstring") == 0) {
4375 if (!*(args[cur_arg + 1])) {
4376 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4377 file, linenum, args[0], args[1], ptr_arg);
4378 err_code |= ERR_ALERT | ERR_FATAL;
4379 goto out;
4380 }
4381 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004382 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004383 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004384 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004385 free(curproxy->expect_regex);
4386 curproxy->expect_regex = NULL;
4387 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004388 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004389 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4390 error = NULL;
4391 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4392 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4393 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4394 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004395 err_code |= ERR_ALERT | ERR_FATAL;
4396 goto out;
4397 }
4398 }
4399 else {
4400 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4401 file, linenum, args[0], args[1], ptr_arg);
4402 err_code |= ERR_ALERT | ERR_FATAL;
4403 goto out;
4404 }
4405 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004406 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004407 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 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004410 }
4411 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004412 else if (!strcmp(args[0], "tcp-check")) {
4413 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4414 err_code |= ERR_WARN;
4415
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004416 if (strcmp(args[1], "connect") == 0) {
4417 const char *ptr_arg;
4418 int cur_arg;
4419 struct tcpcheck_rule *tcpcheck;
4420 struct list *l;
4421
4422 /* check if first rule is also a 'connect' action */
4423 l = (struct list *)&curproxy->tcpcheck_rules;
4424 if (l->p != l->n) {
4425 tcpcheck = (struct tcpcheck_rule *)l->n;
4426 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4427 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4428 file, linenum);
4429 err_code |= ERR_ALERT | ERR_FATAL;
4430 goto out;
4431 }
4432 }
4433
4434 cur_arg = 2;
4435 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4436 tcpcheck->action = TCPCHK_ACT_CONNECT;
4437
4438 /* parsing each parameters to fill up the rule */
4439 while (*(ptr_arg = args[cur_arg])) {
4440 /* tcp port */
4441 if (strcmp(args[cur_arg], "port") == 0) {
4442 if ( (atol(args[cur_arg + 1]) > 65535) ||
4443 (atol(args[cur_arg + 1]) < 1) ){
4444 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4445 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4446 err_code |= ERR_ALERT | ERR_FATAL;
4447 goto out;
4448 }
4449 tcpcheck->port = atol(args[cur_arg + 1]);
4450 cur_arg += 2;
4451 }
4452 /* send proxy protocol */
4453 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4454 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4455 cur_arg++;
4456 }
4457#ifdef USE_OPENSSL
4458 else if (strcmp(args[cur_arg], "ssl") == 0) {
4459 curproxy->options |= PR_O_TCPCHK_SSL;
4460 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4461 cur_arg++;
4462 }
4463#endif /* USE_OPENSSL */
4464 else {
4465#ifdef USE_OPENSSL
4466 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4467#else /* USE_OPENSSL */
4468 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4469#endif /* USE_OPENSSL */
4470 file, linenum, args[0], args[1], args[cur_arg]);
4471 err_code |= ERR_ALERT | ERR_FATAL;
4472 goto out;
4473 }
4474
4475 }
4476
4477 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4478 }
4479 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004480 if (! *(args[2]) ) {
4481 /* SEND string expected */
4482 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4483 file, linenum, args[0], args[1], args[2]);
4484 err_code |= ERR_ALERT | ERR_FATAL;
4485 goto out;
4486 } else {
4487 struct tcpcheck_rule *tcpcheck;
4488
4489 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4490
4491 tcpcheck->action = TCPCHK_ACT_SEND;
4492 tcpcheck->string_len = strlen(args[2]);
4493 tcpcheck->string = strdup(args[2]);
4494 tcpcheck->expect_regex = NULL;
4495
4496 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4497 }
4498 }
4499 else if (strcmp(args[1], "send-binary") == 0) {
4500 if (! *(args[2]) ) {
4501 /* SEND binary string expected */
4502 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4503 file, linenum, args[0], args[1], args[2]);
4504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 } else {
4507 struct tcpcheck_rule *tcpcheck;
4508 char *err = NULL;
4509
4510 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4511
4512 tcpcheck->action = TCPCHK_ACT_SEND;
4513 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4514 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4515 file, linenum, args[0], args[1], args[2], err);
4516 err_code |= ERR_ALERT | ERR_FATAL;
4517 goto out;
4518 }
4519 tcpcheck->expect_regex = NULL;
4520
4521 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4522 }
4523 }
4524 else if (strcmp(args[1], "expect") == 0) {
4525 const char *ptr_arg;
4526 int cur_arg;
4527 int inverse = 0;
4528
4529 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4530 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4531 err_code |= ERR_ALERT | ERR_FATAL;
4532 goto out;
4533 }
4534
4535 cur_arg = 2;
4536 /* consider exclamation marks, sole or at the beginning of a word */
4537 while (*(ptr_arg = args[cur_arg])) {
4538 while (*ptr_arg == '!') {
4539 inverse = !inverse;
4540 ptr_arg++;
4541 }
4542 if (*ptr_arg)
4543 break;
4544 cur_arg++;
4545 }
4546 /* now ptr_arg points to the beginning of a word past any possible
4547 * exclamation mark, and cur_arg is the argument which holds this word.
4548 */
4549 if (strcmp(ptr_arg, "binary") == 0) {
4550 if (!*(args[cur_arg + 1])) {
4551 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4552 file, linenum, args[0], args[1], ptr_arg);
4553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
4555 }
4556 struct tcpcheck_rule *tcpcheck;
4557 char *err = NULL;
4558
4559 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4560
4561 tcpcheck->action = TCPCHK_ACT_EXPECT;
4562 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4563 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4564 file, linenum, args[0], args[1], args[2], err);
4565 err_code |= ERR_ALERT | ERR_FATAL;
4566 goto out;
4567 }
4568 tcpcheck->expect_regex = NULL;
4569 tcpcheck->inverse = inverse;
4570
4571 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4572 }
4573 else if (strcmp(ptr_arg, "string") == 0) {
4574 if (!*(args[cur_arg + 1])) {
4575 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4576 file, linenum, args[0], args[1], ptr_arg);
4577 err_code |= ERR_ALERT | ERR_FATAL;
4578 goto out;
4579 }
4580 struct tcpcheck_rule *tcpcheck;
4581
4582 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4583
4584 tcpcheck->action = TCPCHK_ACT_EXPECT;
4585 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4586 tcpcheck->string = strdup(args[cur_arg + 1]);
4587 tcpcheck->expect_regex = NULL;
4588 tcpcheck->inverse = inverse;
4589
4590 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4591 }
4592 else if (strcmp(ptr_arg, "rstring") == 0) {
4593 if (!*(args[cur_arg + 1])) {
4594 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4595 file, linenum, args[0], args[1], ptr_arg);
4596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
4598 }
4599 struct tcpcheck_rule *tcpcheck;
4600
4601 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4602
4603 tcpcheck->action = TCPCHK_ACT_EXPECT;
4604 tcpcheck->string_len = 0;
4605 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004606 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4607 error = NULL;
4608 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4609 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4610 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4611 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
4615 tcpcheck->inverse = inverse;
4616
4617 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4618 }
4619 else {
4620 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4621 file, linenum, args[0], args[1], ptr_arg);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625 }
4626 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004627 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004628 err_code |= ERR_ALERT | ERR_FATAL;
4629 goto out;
4630 }
4631 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004632 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004633 if (curproxy == &defproxy) {
4634 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004635 err_code |= ERR_ALERT | ERR_FATAL;
4636 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004637 }
4638
Willy Tarreaub80c2302007-11-30 20:51:32 +01004639 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004640 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004641
4642 if (strcmp(args[1], "fail") == 0) {
4643 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004644 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004645 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4646 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004647 err_code |= ERR_ALERT | ERR_FATAL;
4648 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004649 }
4650
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004651 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4652 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4653 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004654 err_code |= ERR_ALERT | ERR_FATAL;
4655 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004656 }
4657 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4658 }
4659 else {
4660 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004661 err_code |= ERR_ALERT | ERR_FATAL;
4662 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004663 }
4664 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004665#ifdef TPROXY
4666 else if (!strcmp(args[0], "transparent")) {
4667 /* enable transparent proxy connections */
4668 curproxy->options |= PR_O_TRANSP;
4669 }
4670#endif
4671 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004672 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004673 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004674
Willy Tarreaubaaee002006-06-26 02:48:02 +02004675 if (*(args[1]) == 0) {
4676 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004677 err_code |= ERR_ALERT | ERR_FATAL;
4678 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004679 }
4680 curproxy->maxconn = atol(args[1]);
4681 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004682 else if (!strcmp(args[0], "backlog")) { /* backlog */
4683 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004684 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004685
4686 if (*(args[1]) == 0) {
4687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004690 }
4691 curproxy->backlog = atol(args[1]);
4692 }
Willy Tarreau86034312006-12-29 00:10:33 +01004693 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004694 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004695 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004696
Willy Tarreau86034312006-12-29 00:10:33 +01004697 if (*(args[1]) == 0) {
4698 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004699 err_code |= ERR_ALERT | ERR_FATAL;
4700 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004701 }
4702 curproxy->fullconn = atol(args[1]);
4703 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004704 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4705 if (*(args[1]) == 0) {
4706 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004709 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004710 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4711 if (err) {
4712 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4713 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004716 }
4717 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004718 }
4719 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004720 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004721 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004722 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004723
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 if (curproxy == &defproxy) {
4725 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_ALERT | ERR_FATAL;
4727 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004728 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004729 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004731
Willy Tarreau902636f2013-03-10 19:44:48 +01004732 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004733 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004734 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004735 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004736 goto out;
4737 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004738
4739 proto = protocol_by_family(sk->ss_family);
4740 if (!proto || !proto->connect) {
4741 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4742 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004743 err_code |= ERR_ALERT | ERR_FATAL;
4744 goto out;
4745 }
4746
4747 if (port1 != port2) {
4748 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4749 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_ALERT | ERR_FATAL;
4751 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004752 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004753
4754 if (!port1) {
4755 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4756 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004757 err_code |= ERR_ALERT | ERR_FATAL;
4758 goto out;
4759 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004760
Willy Tarreaud5191e72010-02-09 20:50:45 +01004761 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004762 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004763 }
4764 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004765 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004766 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004767
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004768 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4769 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004772 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004774 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004775 /**
4776 * The syntax for hash-type config element is
4777 * hash-type {map-based|consistent} [[<algo>] avalanche]
4778 *
4779 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4780 */
4781 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004782
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004783 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4784 err_code |= ERR_WARN;
4785
4786 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004787 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4788 }
4789 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004790 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4791 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004792 else if (strcmp(args[1], "avalanche") == 0) {
4793 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]);
4794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004796 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004797 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004798 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
Bhaskar98634f02013-10-29 23:30:51 -04004802
4803 /* set the hash function to use */
4804 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004805 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004806 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004807
4808 /* if consistent with no argument, then avalanche modifier is also applied */
4809 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4810 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004811 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004812 /* set the hash function */
4813 if (!strcmp(args[2], "sdbm")) {
4814 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4815 }
4816 else if (!strcmp(args[2], "djb2")) {
4817 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004818 } else if (!strcmp(args[2], "wt6")) {
4819 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004820 }
4821 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004822 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 -05004823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
4826
4827 /* set the hash modifier */
4828 if (!strcmp(args[3], "avalanche")) {
4829 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4830 }
4831 else if (*args[3]) {
4832 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4833 err_code |= ERR_ALERT | ERR_FATAL;
4834 goto out;
4835 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004836 }
William Lallemanda73203e2012-03-12 12:48:57 +01004837 }
William Lallemanda73203e2012-03-12 12:48:57 +01004838 else if (strcmp(args[0], "unique-id-format") == 0) {
4839 if (!*(args[1])) {
4840 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4841 err_code |= ERR_ALERT | ERR_FATAL;
4842 goto out;
4843 }
William Lallemand3203ff42012-11-11 17:30:56 +01004844 if (*(args[2])) {
4845 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4846 err_code |= ERR_ALERT | ERR_FATAL;
4847 goto out;
4848 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004849 free(curproxy->conf.uniqueid_format_string);
4850 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004851
Willy Tarreau62a61232013-04-12 18:13:46 +02004852 free(curproxy->conf.uif_file);
4853 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4854 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004855 }
William Lallemanda73203e2012-03-12 12:48:57 +01004856
4857 else if (strcmp(args[0], "unique-id-header") == 0) {
4858 if (!*(args[1])) {
4859 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
4862 }
4863 free(curproxy->header_unique_id);
4864 curproxy->header_unique_id = strdup(args[1]);
4865 }
4866
William Lallemand723b73a2012-02-08 16:37:49 +01004867 else if (strcmp(args[0], "log-format") == 0) {
4868 if (!*(args[1])) {
4869 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4870 err_code |= ERR_ALERT | ERR_FATAL;
4871 goto out;
4872 }
William Lallemand3203ff42012-11-11 17:30:56 +01004873 if (*(args[2])) {
4874 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
4877 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004878
Willy Tarreau62a61232013-04-12 18:13:46 +02004879 if (curproxy->conf.logformat_string != default_http_log_format &&
4880 curproxy->conf.logformat_string != default_tcp_log_format &&
4881 curproxy->conf.logformat_string != clf_http_log_format)
4882 free(curproxy->conf.logformat_string);
4883 curproxy->conf.logformat_string = strdup(args[1]);
4884
4885 free(curproxy->conf.lfs_file);
4886 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4887 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004888
4889 /* get a chance to improve log-format error reporting by
4890 * reporting the correct line-number when possible.
4891 */
4892 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4893 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4894 file, linenum, curproxy->id);
4895 err_code |= ERR_WARN;
4896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897 }
William Lallemand723b73a2012-02-08 16:37:49 +01004898
William Lallemand0f99e342011-10-12 17:50:54 +02004899 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4900 /* delete previous herited or defined syslog servers */
4901 struct logsrv *back;
4902
4903 if (*(args[1]) != 0) {
4904 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
4907 }
4908
William Lallemand723b73a2012-02-08 16:37:49 +01004909 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4910 LIST_DEL(&tmplogsrv->list);
4911 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004912 }
4913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004914 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004915 struct logsrv *logsrv;
4916
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004918 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004919 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004920 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004921 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004922 LIST_INIT(&node->list);
4923 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
4926 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004927 struct sockaddr_storage *sk;
4928 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004929 int arg = 0;
4930 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004931
4932 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933
Willy Tarreau18324f52014-06-27 18:10:07 +02004934 /* just after the address, a length may be specified */
4935 if (strcmp(args[arg+2], "len") == 0) {
4936 len = atoi(args[arg+3]);
4937 if (len < 80 || len > 65535) {
4938 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4939 file, linenum, args[arg+3]);
4940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942 }
4943 logsrv->maxlen = len;
4944
4945 /* skip these two args */
4946 arg += 2;
4947 }
4948 else
4949 logsrv->maxlen = MAX_SYSLOG_LEN;
4950
4951 if (logsrv->maxlen > global.max_syslog_len) {
4952 global.max_syslog_len = logsrv->maxlen;
4953 logline = realloc(logline, global.max_syslog_len + 1);
4954 }
4955
4956 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004957 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004958 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
4961
Willy Tarreaubaaee002006-06-26 02:48:02 +02004962 }
4963
William Lallemand0f99e342011-10-12 17:50:54 +02004964 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004965 if (*(args[arg+3])) {
4966 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004967 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004968 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004969 err_code |= ERR_ALERT | ERR_FATAL;
4970 goto out;
4971
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 }
4974
William Lallemand0f99e342011-10-12 17:50:54 +02004975 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02004976 if (*(args[arg+4])) {
4977 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004978 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004979 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
4982
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004983 }
4984 }
4985
Willy Tarreau902636f2013-03-10 19:44:48 +01004986 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004987 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004988 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004989 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004990 goto out;
4991 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004992
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004993 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004994
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004995 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004996 if (port1 != port2) {
4997 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4998 file, linenum, args[0], args[1]);
4999 err_code |= ERR_ALERT | ERR_FATAL;
5000 goto out;
5001 }
5002
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005003 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005004 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005005 }
William Lallemand0f99e342011-10-12 17:50:54 +02005006
5007 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005008 }
5009 else {
5010 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5011 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005012 err_code |= ERR_ALERT | ERR_FATAL;
5013 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 }
5015 }
5016 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005017 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005018 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005019 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005020 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005021
Willy Tarreau977b8e42006-12-29 14:19:17 +01005022 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005023 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005024
Willy Tarreaubaaee002006-06-26 02:48:02 +02005025 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005026 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5027 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005030 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005031
5032 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005033 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5034 free(curproxy->conn_src.iface_name);
5035 curproxy->conn_src.iface_name = NULL;
5036 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005037
Willy Tarreau902636f2013-03-10 19:44:48 +01005038 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005039 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005040 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005041 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005042 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005043 goto out;
5044 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005045
5046 proto = protocol_by_family(sk->ss_family);
5047 if (!proto || !proto->connect) {
5048 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005049 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
5052 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005053
5054 if (port1 != port2) {
5055 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5056 file, linenum, args[0], args[1]);
5057 err_code |= ERR_ALERT | ERR_FATAL;
5058 goto out;
5059 }
5060
Willy Tarreauef9a3602012-12-08 22:29:20 +01005061 curproxy->conn_src.source_addr = *sk;
5062 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005063
5064 cur_arg = 2;
5065 while (*(args[cur_arg])) {
5066 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005067#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5068#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005069 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005070 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5071 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005072 err_code |= ERR_ALERT | ERR_FATAL;
5073 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005074 }
5075#endif
5076 if (!*args[cur_arg + 1]) {
5077 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5078 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005079 err_code |= ERR_ALERT | ERR_FATAL;
5080 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005081 }
5082
5083 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005084 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5085 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005086 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005087 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5088 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005089 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5090 char *name, *end;
5091
5092 name = args[cur_arg+1] + 7;
5093 while (isspace(*name))
5094 name++;
5095
5096 end = name;
5097 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5098 end++;
5099
Willy Tarreauef9a3602012-12-08 22:29:20 +01005100 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5101 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5102 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5103 curproxy->conn_src.bind_hdr_len = end - name;
5104 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5105 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5106 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005107
5108 /* now look for an occurrence number */
5109 while (isspace(*end))
5110 end++;
5111 if (*end == ',') {
5112 end++;
5113 name = end;
5114 if (*end == '-')
5115 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005116 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005117 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005118 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005119 }
5120
Willy Tarreauef9a3602012-12-08 22:29:20 +01005121 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005122 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5123 " occurrences values smaller than %d.\n",
5124 file, linenum, MAX_HDR_HISTORY);
5125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
5127 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005128 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005129 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005130
Willy Tarreau902636f2013-03-10 19:44:48 +01005131 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005132 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005133 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005134 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005135 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005136 goto out;
5137 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005138
5139 proto = protocol_by_family(sk->ss_family);
5140 if (!proto || !proto->connect) {
5141 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5142 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005143 err_code |= ERR_ALERT | ERR_FATAL;
5144 goto out;
5145 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005146
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005147 if (port1 != port2) {
5148 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5149 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005150 err_code |= ERR_ALERT | ERR_FATAL;
5151 goto out;
5152 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005153 curproxy->conn_src.tproxy_addr = *sk;
5154 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005155 }
5156 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005157#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005158 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005159#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005160#else /* no TPROXY support */
5161 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005162 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005165#endif
5166 cur_arg += 2;
5167 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005168 }
5169
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005170 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5171#ifdef SO_BINDTODEVICE
5172 if (!*args[cur_arg + 1]) {
5173 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5174 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005175 err_code |= ERR_ALERT | ERR_FATAL;
5176 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005177 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005178 free(curproxy->conn_src.iface_name);
5179 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5180 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005181 global.last_checks |= LSTCHK_NETADM;
5182#else
5183 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5184 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005187#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005188 cur_arg += 2;
5189 continue;
5190 }
5191 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005192 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005193 err_code |= ERR_ALERT | ERR_FATAL;
5194 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005197 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5198 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5199 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005200 err_code |= ERR_ALERT | ERR_FATAL;
5201 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005203 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005205 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5206 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005209 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210
5211 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005212 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005213 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005214 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 }
5217 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005219 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005220 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
5224 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005226 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005227 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
5231 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005233 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
5238 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005245 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005247 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005250 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005251 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005252 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005258
5259 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5260 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 +01005261 }
5262 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005264 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005265 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005266 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005267 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005268
5269 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5270 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 +01005271 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005273 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5275 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005278 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279
5280 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005281 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005282 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005283 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 }
5286 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005287 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005288 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005289 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005290 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
5293 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005295 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005296 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005297 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005298 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
5300 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005302 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005303 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005304 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
5307 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005309 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005310 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005314 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005315 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005316 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005317 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005319 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005322 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005323
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 if (curproxy == &defproxy) {
5325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005329 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005330 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005331
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 if (*(args[1]) == 0) {
5333 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005334 err_code |= ERR_ALERT | ERR_FATAL;
5335 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005336 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005337
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005338 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005339 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5340 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5341 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005345 err_code |= warnif_cond_conflicts(cond,
5346 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5347 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005348 }
5349 else if (*args[2]) {
5350 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5351 file, linenum, args[0], args[2]);
5352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
5354 }
5355
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005356 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005357 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005358 wl->s = strdup(args[1]);
5359 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005360 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005361 }
5362 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005363 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5365 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
Willy Tarreauade5ec42010-01-28 19:33:49 +01005370 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005371 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005372 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005373 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005374 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005375 }
5376 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005377 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005378 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005379 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005380 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005381 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005382 }
5383 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005384 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005385 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005386 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005387 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
5390 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005391 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5393 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005394 err_code |= ERR_ALERT | ERR_FATAL;
5395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005396 }
5397
Willy Tarreauade5ec42010-01-28 19:33:49 +01005398 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005399 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005400 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005401 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005403 }
5404 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005405 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005406 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005407 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005408 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005410 }
5411 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005412 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005413 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005414 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005415 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005416 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417 }
5418 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005419 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005420
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 if (curproxy == &defproxy) {
5422 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005423 err_code |= ERR_ALERT | ERR_FATAL;
5424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005426 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005427 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428
Willy Tarreaubaaee002006-06-26 02:48:02 +02005429 if (*(args[1]) == 0) {
5430 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_ALERT | ERR_FATAL;
5432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 }
5434
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005435 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005436 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5437 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5438 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005439 err_code |= ERR_ALERT | ERR_FATAL;
5440 goto out;
5441 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005442 err_code |= warnif_cond_conflicts(cond,
5443 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5444 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005445 }
5446 else if (*args[2]) {
5447 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5448 file, linenum, args[0], args[2]);
5449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 }
5452
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005453 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005454 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005455 wl->s = strdup(args[1]);
5456 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 }
5458 else if (!strcmp(args[0], "errorloc") ||
5459 !strcmp(args[0], "errorloc302") ||
5460 !strcmp(args[0], "errorloc303")) { /* error location */
5461 int errnum, errlen;
5462 char *err;
5463
Willy Tarreau977b8e42006-12-29 14:19:17 +01005464 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005465 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005466
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005468 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005469 err_code |= ERR_ALERT | ERR_FATAL;
5470 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471 }
5472
5473 errnum = atol(args[1]);
5474 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005475 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5476 err = malloc(errlen);
5477 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005478 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005479 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5480 err = malloc(errlen);
5481 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 }
5483
Willy Tarreau0f772532006-12-23 20:51:41 +01005484 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5485 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005486 chunk_destroy(&curproxy->errmsg[rc]);
5487 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005488 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005490 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005491
5492 if (rc >= HTTP_ERR_SIZE) {
5493 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5494 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 free(err);
5496 }
5497 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005498 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5499 int errnum, errlen, fd;
5500 char *err;
5501 struct stat stat;
5502
5503 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005504 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005505
5506 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005507 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005508 err_code |= ERR_ALERT | ERR_FATAL;
5509 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005510 }
5511
5512 fd = open(args[2], O_RDONLY);
5513 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5514 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5515 file, linenum, args[2], args[1]);
5516 if (fd >= 0)
5517 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005520 }
5521
Willy Tarreau27a674e2009-08-17 07:23:33 +02005522 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005523 errlen = stat.st_size;
5524 } else {
5525 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005526 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005527 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005528 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005529 }
5530
5531 err = malloc(errlen); /* malloc() must succeed during parsing */
5532 errnum = read(fd, err, errlen);
5533 if (errnum != errlen) {
5534 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5535 file, linenum, args[2], args[1]);
5536 close(fd);
5537 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005540 }
5541 close(fd);
5542
5543 errnum = atol(args[1]);
5544 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5545 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005546 chunk_destroy(&curproxy->errmsg[rc]);
5547 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005548 break;
5549 }
5550 }
5551
5552 if (rc >= HTTP_ERR_SIZE) {
5553 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5554 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005555 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005556 free(err);
5557 }
5558 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005559 else if (!strcmp(args[0], "compression")) {
5560 struct comp *comp;
5561 if (curproxy->comp == NULL) {
5562 comp = calloc(1, sizeof(struct comp));
5563 curproxy->comp = comp;
5564 } else {
5565 comp = curproxy->comp;
5566 }
5567
5568 if (!strcmp(args[1], "algo")) {
5569 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005570 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005571
William Lallemand82fe75c2012-10-23 10:25:10 +02005572 cur_arg = 2;
5573 if (!*args[cur_arg]) {
5574 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5575 file, linenum, args[0]);
5576 err_code |= ERR_ALERT | ERR_FATAL;
5577 goto out;
5578 }
5579 while (*(args[cur_arg])) {
5580 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5581 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5582 file, linenum, args[0], args[cur_arg]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
William Lallemand552df672012-11-07 13:21:47 +01005586 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5587 curproxy->comp->algos->end(&ctx);
5588 } else {
5589 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5590 file, linenum, args[0], args[cur_arg]);
5591 err_code |= ERR_ALERT | ERR_FATAL;
5592 goto out;
5593 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005594 cur_arg ++;
5595 continue;
5596 }
5597 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005598 else if (!strcmp(args[1], "offload")) {
5599 comp->offload = 1;
5600 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005601 else if (!strcmp(args[1], "type")) {
5602 int cur_arg;
5603 cur_arg = 2;
5604 if (!*args[cur_arg]) {
5605 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5606 file, linenum, args[0]);
5607 err_code |= ERR_ALERT | ERR_FATAL;
5608 goto out;
5609 }
5610 while (*(args[cur_arg])) {
5611 comp_append_type(comp, args[cur_arg]);
5612 cur_arg ++;
5613 continue;
5614 }
5615 }
5616 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005617 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005618 file, linenum, args[0]);
5619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
5622 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005624 struct cfg_kw_list *kwl;
5625 int index;
5626
5627 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5628 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5629 if (kwl->kw[index].section != CFG_LISTEN)
5630 continue;
5631 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5632 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005633 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005634 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005635 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005636 err_code |= ERR_ALERT | ERR_FATAL;
5637 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005638 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005639 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005640 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005641 err_code |= ERR_WARN;
5642 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005643 }
Willy Tarreau93893792009-07-23 13:19:11 +02005644 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005645 }
5646 }
5647 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005648
Willy Tarreau6daf3432008-01-22 16:44:08 +01005649 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005650 err_code |= ERR_ALERT | ERR_FATAL;
5651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 }
Willy Tarreau93893792009-07-23 13:19:11 +02005653 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005654 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005655 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005656}
5657
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005658int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005659cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5660{
5661#ifdef CONFIG_HAP_NS
5662 const char *err;
5663 const char *item = args[0];
5664
5665 if (!strcmp(item, "namespace_list")) {
5666 return 0;
5667 }
5668 else if (!strcmp(item, "namespace")) {
5669 size_t idx = 1;
5670 const char *current;
5671 while (*(current = args[idx++])) {
5672 err = invalid_char(current);
5673 if (err) {
5674 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5675 file, linenum, *err, item, current);
5676 return ERR_ALERT | ERR_FATAL;
5677 }
5678
5679 if (netns_store_lookup(current, strlen(current))) {
5680 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5681 file, linenum, current);
5682 return ERR_ALERT | ERR_FATAL;
5683 }
5684 if (!netns_store_insert(current)) {
5685 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5686 file, linenum, current);
5687 return ERR_ALERT | ERR_FATAL;
5688 }
5689 }
5690 }
5691
5692 return 0;
5693#else
5694 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5695 file, linenum);
5696 return ERR_ALERT | ERR_FATAL;
5697#endif
5698}
5699
5700int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005701cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5702{
5703
5704 int err_code = 0;
5705 const char *err;
5706
5707 if (!strcmp(args[0], "userlist")) { /* new userlist */
5708 struct userlist *newul;
5709
5710 if (!*args[1]) {
5711 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5712 file, linenum, args[0]);
5713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
5715 }
5716
5717 err = invalid_char(args[1]);
5718 if (err) {
5719 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5720 file, linenum, *err, args[0], args[1]);
5721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
5723 }
5724
5725 for (newul = userlist; newul; newul = newul->next)
5726 if (!strcmp(newul->name, args[1])) {
5727 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5728 file, linenum, args[1]);
5729 err_code |= ERR_WARN;
5730 goto out;
5731 }
5732
5733 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5734 if (!newul) {
5735 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5736 err_code |= ERR_ALERT | ERR_ABORT;
5737 goto out;
5738 }
5739
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005740 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005741 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005742 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5743 err_code |= ERR_ALERT | ERR_ABORT;
5744 goto out;
5745 }
5746
5747 newul->next = userlist;
5748 userlist = newul;
5749
5750 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005751 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005752 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005753 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005754
5755 if (!*args[1]) {
5756 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5757 file, linenum, args[0]);
5758 err_code |= ERR_ALERT | ERR_FATAL;
5759 goto out;
5760 }
5761
5762 err = invalid_char(args[1]);
5763 if (err) {
5764 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5765 file, linenum, *err, args[0], args[1]);
5766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
5768 }
5769
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005770 for (ag = userlist->groups; ag; ag = ag->next)
5771 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005772 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5773 file, linenum, args[1], userlist->name);
5774 err_code |= ERR_ALERT;
5775 goto out;
5776 }
5777
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005778 ag = calloc(1, sizeof(*ag));
5779 if (!ag) {
5780 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5781 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005782 goto out;
5783 }
5784
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005785 ag->name = strdup(args[1]);
5786 if (!ag) {
5787 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5788 err_code |= ERR_ALERT | ERR_ABORT;
5789 goto out;
5790 }
5791
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005792 cur_arg = 2;
5793
5794 while (*args[cur_arg]) {
5795 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005796 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005797 cur_arg += 2;
5798 continue;
5799 } else {
5800 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5801 file, linenum, args[0]);
5802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
5804 }
5805 }
5806
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005807 ag->next = userlist->groups;
5808 userlist->groups = ag;
5809
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005810 } else if (!strcmp(args[0], "user")) { /* new user */
5811 struct auth_users *newuser;
5812 int cur_arg;
5813
5814 if (!*args[1]) {
5815 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5816 file, linenum, args[0]);
5817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
5819 }
5820
5821 for (newuser = userlist->users; newuser; newuser = newuser->next)
5822 if (!strcmp(newuser->user, args[1])) {
5823 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5824 file, linenum, args[1], userlist->name);
5825 err_code |= ERR_ALERT;
5826 goto out;
5827 }
5828
5829 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5830 if (!newuser) {
5831 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5832 err_code |= ERR_ALERT | ERR_ABORT;
5833 goto out;
5834 }
5835
5836 newuser->user = strdup(args[1]);
5837
5838 newuser->next = userlist->users;
5839 userlist->users = newuser;
5840
5841 cur_arg = 2;
5842
5843 while (*args[cur_arg]) {
5844 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02005845#ifdef CONFIG_HAP_CRYPT
5846 if (!crypt("", args[cur_arg + 1])) {
5847 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5848 file, linenum, newuser->user);
5849 err_code |= ERR_ALERT | ERR_FATAL;
5850 goto out;
5851 }
5852#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005853 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5854 file, linenum);
5855 err_code |= ERR_ALERT;
5856#endif
5857 newuser->pass = strdup(args[cur_arg + 1]);
5858 cur_arg += 2;
5859 continue;
5860 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5861 newuser->pass = strdup(args[cur_arg + 1]);
5862 newuser->flags |= AU_O_INSECURE;
5863 cur_arg += 2;
5864 continue;
5865 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005866 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005867 cur_arg += 2;
5868 continue;
5869 } else {
5870 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5871 file, linenum, args[0]);
5872 err_code |= ERR_ALERT | ERR_FATAL;
5873 goto out;
5874 }
5875 }
5876 } else {
5877 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5878 err_code |= ERR_ALERT | ERR_FATAL;
5879 }
5880
5881out:
5882 return err_code;
5883}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005884
5885/*
5886 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005887 * Returns the error code, 0 if OK, or any combination of :
5888 * - ERR_ABORT: must abort ASAP
5889 * - ERR_FATAL: we can continue parsing but not start the service
5890 * - ERR_WARN: a warning has been emitted
5891 * - ERR_ALERT: an alert has been emitted
5892 * Only the two first ones can stop processing, the two others are just
5893 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005894 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005895int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005896{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005897 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005898 FILE *f;
5899 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005900 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005901 struct cfg_section *cs = NULL;
5902 struct cfg_section *ics;
5903
5904 /* Register internal sections */
5905 if (!cfg_register_section("listen", cfg_parse_listen) ||
5906 !cfg_register_section("frontend", cfg_parse_listen) ||
5907 !cfg_register_section("backend", cfg_parse_listen) ||
5908 !cfg_register_section("ruleset", cfg_parse_listen) ||
5909 !cfg_register_section("defaults", cfg_parse_listen) ||
5910 !cfg_register_section("global", cfg_parse_global) ||
5911 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005912 !cfg_register_section("peers", cfg_parse_peers) ||
5913 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005914 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 if ((f=fopen(file,"r")) == NULL)
5917 return -1;
5918
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005919 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005920 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005921 char *end;
5922 char *args[MAX_LINE_ARGS + 1];
5923 char *line = thisline;
5924
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 linenum++;
5926
5927 end = line + strlen(line);
5928
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005929 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5930 /* Check if we reached the limit and the last char is not \n.
5931 * Watch out for the last line without the terminating '\n'!
5932 */
5933 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005934 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005935 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005936 }
5937
Willy Tarreaubaaee002006-06-26 02:48:02 +02005938 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005939 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005940 line++;
5941
5942 arg = 0;
5943 args[arg] = line;
5944
5945 while (*line && arg < MAX_LINE_ARGS) {
5946 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5947 * C equivalent value. Other combinations left unchanged (eg: \1).
5948 */
5949 if (*line == '\\') {
5950 int skip = 0;
5951 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5952 *line = line[1];
5953 skip = 1;
5954 }
5955 else if (line[1] == 'r') {
5956 *line = '\r';
5957 skip = 1;
5958 }
5959 else if (line[1] == 'n') {
5960 *line = '\n';
5961 skip = 1;
5962 }
5963 else if (line[1] == 't') {
5964 *line = '\t';
5965 skip = 1;
5966 }
5967 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005968 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005969 unsigned char hex1, hex2;
5970 hex1 = toupper(line[2]) - '0';
5971 hex2 = toupper(line[3]) - '0';
5972 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5973 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5974 *line = (hex1<<4) + hex2;
5975 skip = 3;
5976 }
5977 else {
5978 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005979 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005980 }
5981 }
5982 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005983 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 end -= skip;
5985 }
5986 line++;
5987 }
5988 else if (*line == '#' || *line == '\n' || *line == '\r') {
5989 /* end of string, end of loop */
5990 *line = 0;
5991 break;
5992 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005993 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005994 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005995 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005996 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 line++;
5998 args[++arg] = line;
5999 }
6000 else {
6001 line++;
6002 }
6003 }
6004
6005 /* empty line */
6006 if (!**args)
6007 continue;
6008
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006009 if (*line) {
6010 /* we had to stop due to too many args.
6011 * Let's terminate the string, print the offending part then cut the
6012 * last arg.
6013 */
6014 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6015 line++;
6016 *line = '\0';
6017
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006018 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006019 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006020 err_code |= ERR_ALERT | ERR_FATAL;
6021 args[arg] = line;
6022 }
6023
Willy Tarreau540abe42007-05-02 20:50:16 +02006024 /* zero out remaining args and ensure that at least one entry
6025 * is zeroed out.
6026 */
6027 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006028 args[arg] = line;
6029 }
6030
Willy Tarreau3842f002009-06-14 11:39:52 +02006031 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006032 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006033 char *tmp;
6034
Willy Tarreau3842f002009-06-14 11:39:52 +02006035 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006036 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006037 for (arg=0; *args[arg+1]; arg++)
6038 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006039 *tmp = '\0'; // fix the next arg to \0
6040 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006041 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006042 else if (!strcmp(args[0], "default")) {
6043 kwm = KWM_DEF;
6044 for (arg=0; *args[arg+1]; arg++)
6045 args[arg] = args[arg+1]; // shift args after inversion
6046 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006047
William Lallemand0f99e342011-10-12 17:50:54 +02006048 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6049 strcmp(args[0], "log") != 0) {
6050 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006051 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006052 }
6053
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006054 /* detect section start */
6055 list_for_each_entry(ics, &sections, list) {
6056 if (strcmp(args[0], ics->section_name) == 0) {
6057 cursection = ics->section_name;
6058 cs = ics;
6059 break;
6060 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006061 }
6062
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006064 if (cs)
6065 err_code |= cs->section_parser(file, linenum, args, kwm);
6066 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006067 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006068 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006069 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006070
6071 if (err_code & ERR_ABORT)
6072 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006073 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006074 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006076 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006077}
6078
Willy Tarreau64ab6072014-09-16 12:17:36 +02006079/* This function propagates processes from frontend <from> to backend <to> so
6080 * that it is always guaranteed that a backend pointed to by a frontend is
6081 * bound to all of its processes. After that, if the target is a "listen"
6082 * instance, the function recursively descends the target's own targets along
6083 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6084 * checked first to ensure that <to> is already bound to all processes of
6085 * <from>, there is no risk of looping and we ensure to follow the shortest
6086 * path to the destination.
6087 *
6088 * It is possible to set <to> to NULL for the first call so that the function
6089 * takes care of visiting the initial frontend in <from>.
6090 *
6091 * It is important to note that the function relies on the fact that all names
6092 * have already been resolved.
6093 */
6094void propagate_processes(struct proxy *from, struct proxy *to)
6095{
6096 struct switching_rule *rule;
6097 struct hdr_exp *exp;
6098
6099 if (to) {
6100 /* check whether we need to go down */
6101 if (from->bind_proc &&
6102 (from->bind_proc & to->bind_proc) == from->bind_proc)
6103 return;
6104
6105 if (!from->bind_proc && !to->bind_proc)
6106 return;
6107
6108 to->bind_proc = from->bind_proc ?
6109 (to->bind_proc | from->bind_proc) : 0;
6110
6111 /* now propagate down */
6112 from = to;
6113 }
6114
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006115 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006116 return;
6117
Willy Tarreauf6b70012014-12-18 14:00:43 +01006118 if (from->state == PR_STSTOPPED)
6119 return;
6120
Willy Tarreau64ab6072014-09-16 12:17:36 +02006121 /* default_backend */
6122 if (from->defbe.be)
6123 propagate_processes(from, from->defbe.be);
6124
6125 /* use_backend */
6126 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006127 if (rule->dynamic)
6128 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006129 to = rule->be.backend;
6130 propagate_processes(from, to);
6131 }
6132
6133 /* reqsetbe */
6134 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6135 if (exp->action != ACT_SETBE)
6136 continue;
6137 to = (struct proxy *)exp->replace;
6138 propagate_processes(from, to);
6139 }
6140}
6141
Willy Tarreaubb925012009-07-23 13:36:36 +02006142/*
6143 * Returns the error code, 0 if OK, or any combination of :
6144 * - ERR_ABORT: must abort ASAP
6145 * - ERR_FATAL: we can continue parsing but not start the service
6146 * - ERR_WARN: a warning has been emitted
6147 * - ERR_ALERT: an alert has been emitted
6148 * Only the two first ones can stop processing, the two others are just
6149 * indicators.
6150 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006151int check_config_validity()
6152{
6153 int cfgerr = 0;
6154 struct proxy *curproxy = NULL;
6155 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006156 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006157 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006158 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006160 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 /*
6162 * Now, check for the integrity of all that we have collected.
6163 */
6164
6165 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006166 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167
Willy Tarreau193b8c62012-11-22 00:17:38 +01006168 if (!global.tune.max_http_hdr)
6169 global.tune.max_http_hdr = MAX_HTTP_HDR;
6170
6171 if (!global.tune.cookie_len)
6172 global.tune.cookie_len = CAPTURE_LEN;
6173
6174 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6175
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006176 /* Post initialisation of the users and groups lists. */
6177 err_code = userlist_postinit();
6178 if (err_code != ERR_NONE)
6179 goto out;
6180
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006181 /* first, we will invert the proxy list order */
6182 curproxy = NULL;
6183 while (proxy) {
6184 struct proxy *next;
6185
6186 next = proxy->next;
6187 proxy->next = curproxy;
6188 curproxy = proxy;
6189 if (!next)
6190 break;
6191 proxy = next;
6192 }
6193
Willy Tarreau419ead82014-09-16 13:41:21 +02006194 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006195 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006196 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006197 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006198 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006199 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006200 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006201 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006202
Willy Tarreau050536d2012-10-04 08:47:34 +02006203 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006204 /* proxy ID not set, use automatic numbering with first
6205 * spare entry starting with next_pxid.
6206 */
6207 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6208 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6209 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006210 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006211 next_pxid++;
6212
Willy Tarreau55ea7572007-06-17 19:56:27 +02006213
Willy Tarreaubaaee002006-06-26 02:48:02 +02006214 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006215 /* ensure we don't keep listeners uselessly bound */
6216 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 continue;
6218 }
6219
Willy Tarreau102df612014-05-07 23:56:38 +02006220 /* Check multi-process mode compatibility for the current proxy */
6221
6222 if (curproxy->bind_proc) {
6223 /* an explicit bind-process was specified, let's check how many
6224 * processes remain.
6225 */
6226 nbproc = popcount(curproxy->bind_proc);
6227
6228 curproxy->bind_proc &= nbits(global.nbproc);
6229 if (!curproxy->bind_proc && nbproc == 1) {
6230 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);
6231 curproxy->bind_proc = 1;
6232 }
6233 else if (!curproxy->bind_proc && nbproc > 1) {
6234 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);
6235 curproxy->bind_proc = 0;
6236 }
6237 }
6238
Willy Tarreau3d209582014-05-09 17:06:11 +02006239 /* check and reduce the bind-proc of each listener */
6240 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6241 unsigned long mask;
6242
6243 if (!bind_conf->bind_proc)
6244 continue;
6245
6246 mask = nbits(global.nbproc);
6247 if (curproxy->bind_proc)
6248 mask &= curproxy->bind_proc;
6249 /* mask cannot be null here thanks to the previous checks */
6250
6251 nbproc = popcount(bind_conf->bind_proc);
6252 bind_conf->bind_proc &= mask;
6253
6254 if (!bind_conf->bind_proc && nbproc == 1) {
6255 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",
6256 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6257 bind_conf->bind_proc = mask & ~(mask - 1);
6258 }
6259 else if (!bind_conf->bind_proc && nbproc > 1) {
6260 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",
6261 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6262 bind_conf->bind_proc = 0;
6263 }
6264 }
6265
Willy Tarreau102df612014-05-07 23:56:38 +02006266 if (global.nbproc > 1 && curproxy->table.peers.name) {
6267 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6268 curproxy->id);
6269 cfgerr++;
6270 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006271
Willy Tarreauff01a212009-03-15 13:46:16 +01006272 switch (curproxy->mode) {
6273 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006274 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006275 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006276 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6277 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006278 cfgerr++;
6279 }
6280
6281 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006282 Warning("config : servers will be ignored for %s '%s'.\n",
6283 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006284 break;
6285
6286 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006287 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006288 break;
6289
6290 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006291 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006292 break;
6293 }
6294
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006295 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006296 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006297 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006298 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6299 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006300 cfgerr++;
6301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006303 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006304 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6305 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006306 cfgerr++;
6307 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006309 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006310 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6311 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006312 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006313 }
6314 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006315 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006316 /* If no LB algo is set in a backend, and we're not in
6317 * transparent mode, dispatch mode nor proxy mode, we
6318 * want to use balance roundrobin by default.
6319 */
6320 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6321 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006322 }
6323 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006324
Willy Tarreau1620ec32011-08-06 17:05:02 +02006325 if (curproxy->options & PR_O_DISPATCH)
6326 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6327 else if (curproxy->options & PR_O_HTTP_PROXY)
6328 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6329 else if (curproxy->options & PR_O_TRANSP)
6330 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006331
Willy Tarreau1620ec32011-08-06 17:05:02 +02006332 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6333 if (curproxy->options & PR_O_DISABLE404) {
6334 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6335 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6336 err_code |= ERR_WARN;
6337 curproxy->options &= ~PR_O_DISABLE404;
6338 }
6339 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6340 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6341 "send-state", proxy_type_str(curproxy), curproxy->id);
6342 err_code |= ERR_WARN;
6343 curproxy->options &= ~PR_O2_CHK_SNDST;
6344 }
Willy Tarreauef781042010-01-27 11:53:01 +01006345 }
6346
Simon Horman98637e52014-06-20 12:30:16 +09006347 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6348 if (!global.external_check) {
6349 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6350 curproxy->id, "option external-check");
6351 cfgerr++;
6352 }
6353 if (!curproxy->check_command) {
6354 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6355 curproxy->id, "option external-check");
6356 cfgerr++;
6357 }
6358 }
6359
6360 if (curproxy->check_command) {
6361 int clear = 0;
6362 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6363 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6364 "external-check command", proxy_type_str(curproxy), curproxy->id);
6365 err_code |= ERR_WARN;
6366 clear = 1;
6367 }
6368 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6369 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6370 curproxy->id, "external-check command");
6371 cfgerr++;
6372 }
6373 if (clear) {
6374 free(curproxy->check_command);
6375 curproxy->check_command = NULL;
6376 }
6377 }
6378
6379 if (curproxy->check_path) {
6380 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6381 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6382 "external-check path", proxy_type_str(curproxy), curproxy->id);
6383 err_code |= ERR_WARN;
6384 free(curproxy->check_path);
6385 curproxy->check_path = NULL;
6386 }
6387 }
6388
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006389 /* if a default backend was specified, let's find it */
6390 if (curproxy->defbe.name) {
6391 struct proxy *target;
6392
Alex Williams96532db2009-11-01 21:27:13 -05006393 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006394 if (!target) {
6395 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6396 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006397 cfgerr++;
6398 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006399 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6400 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006401 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006402 } else {
6403 free(curproxy->defbe.name);
6404 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006405
6406 /* Emit a warning if this proxy also has some servers */
6407 if (curproxy->srv) {
6408 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6409 curproxy->id);
6410 err_code |= ERR_WARN;
6411 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
6413 }
6414
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006415 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006416 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6417 /* map jump target for ACT_SETBE in req_rep chain */
6418 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006419 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006420 struct proxy *target;
6421
Willy Tarreaua496b602006-12-17 23:15:24 +01006422 if (exp->action != ACT_SETBE)
6423 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006424
Alex Williams96532db2009-11-01 21:27:13 -05006425 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006426 if (!target) {
6427 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6428 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006429 cfgerr++;
6430 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006431 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6432 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006433 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006434 } else {
6435 free((void *)exp->replace);
6436 exp->replace = (const char *)target;
6437 }
6438 }
6439 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006440
6441 /* find the target proxy for 'use_backend' rules */
6442 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006443 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006444 struct logformat_node *node;
6445 char *pxname;
6446
6447 /* Try to parse the string as a log format expression. If the result
6448 * of the parsing is only one entry containing a simple string, then
6449 * it's a standard string corresponding to a static rule, thus the
6450 * parsing is cancelled and be.name is restored to be resolved.
6451 */
6452 pxname = rule->be.name;
6453 LIST_INIT(&rule->be.expr);
6454 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6455 curproxy->conf.args.file, curproxy->conf.args.line);
6456 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6457
6458 if (!LIST_ISEMPTY(&rule->be.expr)) {
6459 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6460 rule->dynamic = 1;
6461 free(pxname);
6462 continue;
6463 }
6464 /* simple string: free the expression and fall back to static rule */
6465 free(node->arg);
6466 free(node);
6467 }
6468
6469 rule->dynamic = 0;
6470 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006471
Alex Williams96532db2009-11-01 21:27:13 -05006472 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006473
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006474 if (!target) {
6475 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6476 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006477 cfgerr++;
6478 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006479 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6480 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006481 cfgerr++;
6482 } else {
6483 free((void *)rule->be.name);
6484 rule->be.backend = target;
6485 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006486 }
6487
Willy Tarreau64ab6072014-09-16 12:17:36 +02006488 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006489 list_for_each_entry(srule, &curproxy->server_rules, list) {
6490 struct server *target = findserver(curproxy, srule->srv.name);
6491
6492 if (!target) {
6493 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6494 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6495 cfgerr++;
6496 continue;
6497 }
6498 free((void *)srule->srv.name);
6499 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006500 }
6501
Emeric Brunb982a3d2010-01-04 15:45:53 +01006502 /* find the target table for 'stick' rules */
6503 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6504 struct proxy *target;
6505
Emeric Brun1d33b292010-01-04 15:47:17 +01006506 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6507 if (mrule->flags & STK_IS_STORE)
6508 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6509
Emeric Brunb982a3d2010-01-04 15:45:53 +01006510 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006511 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006512 else
6513 target = curproxy;
6514
6515 if (!target) {
6516 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6517 curproxy->id, mrule->table.name);
6518 cfgerr++;
6519 }
6520 else if (target->table.size == 0) {
6521 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6522 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6523 cfgerr++;
6524 }
Willy Tarreau12785782012-04-27 21:37:17 +02006525 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6526 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006527 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6528 cfgerr++;
6529 }
6530 else {
6531 free((void *)mrule->table.name);
6532 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006533 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006534 }
6535 }
6536
6537 /* find the target table for 'store response' rules */
6538 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6539 struct proxy *target;
6540
Emeric Brun1d33b292010-01-04 15:47:17 +01006541 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6542
Emeric Brunb982a3d2010-01-04 15:45:53 +01006543 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006544 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006545 else
6546 target = curproxy;
6547
6548 if (!target) {
6549 Alert("Proxy '%s': unable to find store table '%s'.\n",
6550 curproxy->id, mrule->table.name);
6551 cfgerr++;
6552 }
6553 else if (target->table.size == 0) {
6554 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6555 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6556 cfgerr++;
6557 }
Willy Tarreau12785782012-04-27 21:37:17 +02006558 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6559 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006560 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6561 cfgerr++;
6562 }
6563 else {
6564 free((void *)mrule->table.name);
6565 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006566 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006567 }
6568 }
6569
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006570 /* find the target table for 'tcp-request' layer 4 rules */
6571 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6572 struct proxy *target;
6573
Willy Tarreaub4c84932013-07-23 19:15:30 +02006574 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006575 continue;
6576
6577 if (trule->act_prm.trk_ctr.table.n)
6578 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6579 else
6580 target = curproxy;
6581
6582 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006583 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6584 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006585 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006586 cfgerr++;
6587 }
6588 else if (target->table.size == 0) {
6589 Alert("Proxy '%s': table '%s' used but not configured.\n",
6590 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6591 cfgerr++;
6592 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006593 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6594 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6595 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 +01006596 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006597 cfgerr++;
6598 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006599 else {
6600 free(trule->act_prm.trk_ctr.table.n);
6601 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006602 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006603 * to pass a list of counters to track and allocate them right here using
6604 * stktable_alloc_data_type().
6605 */
6606 }
6607 }
6608
Willy Tarreaud1f96522010-08-03 19:34:32 +02006609 /* find the target table for 'tcp-request' layer 6 rules */
6610 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6611 struct proxy *target;
6612
Willy Tarreaub4c84932013-07-23 19:15:30 +02006613 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006614 continue;
6615
6616 if (trule->act_prm.trk_ctr.table.n)
6617 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6618 else
6619 target = curproxy;
6620
6621 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006622 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6623 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006624 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006625 cfgerr++;
6626 }
6627 else if (target->table.size == 0) {
6628 Alert("Proxy '%s': table '%s' used but not configured.\n",
6629 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6630 cfgerr++;
6631 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006632 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6633 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6634 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 +01006635 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006636 cfgerr++;
6637 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006638 else {
6639 free(trule->act_prm.trk_ctr.table.n);
6640 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006641 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006642 * to pass a list of counters to track and allocate them right here using
6643 * stktable_alloc_data_type().
6644 */
6645 }
6646 }
6647
Willy Tarreau09448f72014-06-25 18:12:15 +02006648 /* find the target table for 'http-request' layer 7 rules */
6649 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6650 struct proxy *target;
6651
6652 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6653 continue;
6654
6655 if (hrqrule->act_prm.trk_ctr.table.n)
6656 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6657 else
6658 target = curproxy;
6659
6660 if (!target) {
6661 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6662 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6663 http_req_trk_idx(hrqrule->action));
6664 cfgerr++;
6665 }
6666 else if (target->table.size == 0) {
6667 Alert("Proxy '%s': table '%s' used but not configured.\n",
6668 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6669 cfgerr++;
6670 }
6671 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6672 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6673 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6674 http_req_trk_idx(hrqrule->action));
6675 cfgerr++;
6676 }
6677 else {
6678 free(hrqrule->act_prm.trk_ctr.table.n);
6679 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6680 /* Note: if we decide to enhance the track-sc syntax, we may be able
6681 * to pass a list of counters to track and allocate them right here using
6682 * stktable_alloc_data_type().
6683 */
6684 }
6685 }
6686
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006687 /* move any "block" rules at the beginning of the http-request rules */
6688 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6689 /* insert block_rules into http_req_rules at the beginning */
6690 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6691 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6692 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6693 curproxy->http_req_rules.n = curproxy->block_rules.n;
6694 LIST_INIT(&curproxy->block_rules);
6695 }
6696
Emeric Brun32da3c42010-09-23 18:39:19 +02006697 if (curproxy->table.peers.name) {
6698 struct peers *curpeers = peers;
6699
6700 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6701 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6702 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006703 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006704 break;
6705 }
6706 }
6707
6708 if (!curpeers) {
6709 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6710 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006711 free((void *)curproxy->table.peers.name);
6712 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006713 cfgerr++;
6714 }
6715 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006716 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6717 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006718 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006719 cfgerr++;
6720 }
6721 }
6722
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006723 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006724 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006725 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6726 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6727 "proxy", curproxy->id);
6728 cfgerr++;
6729 goto out_uri_auth_compat;
6730 }
6731
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006732 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006733 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006734 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006735 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006736
Willy Tarreau95fa4692010-02-01 13:05:50 +01006737 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6738 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006739
6740 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006741 uri_auth_compat_req[i++] = "realm";
6742 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6743 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006744
Willy Tarreau95fa4692010-02-01 13:05:50 +01006745 uri_auth_compat_req[i++] = "unless";
6746 uri_auth_compat_req[i++] = "{";
6747 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6748 uri_auth_compat_req[i++] = "}";
6749 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006750
Willy Tarreauff011f22011-01-06 17:51:27 +01006751 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6752 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006753 cfgerr++;
6754 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006755 }
6756
Willy Tarreauff011f22011-01-06 17:51:27 +01006757 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006758
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006759 if (curproxy->uri_auth->auth_realm) {
6760 free(curproxy->uri_auth->auth_realm);
6761 curproxy->uri_auth->auth_realm = NULL;
6762 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006763
6764 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006765 }
6766out_uri_auth_compat:
6767
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006768 /* compile the log format */
6769 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006770 if (curproxy->conf.logformat_string != default_http_log_format &&
6771 curproxy->conf.logformat_string != default_tcp_log_format &&
6772 curproxy->conf.logformat_string != clf_http_log_format)
6773 free(curproxy->conf.logformat_string);
6774 curproxy->conf.logformat_string = NULL;
6775 free(curproxy->conf.lfs_file);
6776 curproxy->conf.lfs_file = NULL;
6777 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006778 }
6779
Willy Tarreau62a61232013-04-12 18:13:46 +02006780 if (curproxy->conf.logformat_string) {
6781 curproxy->conf.args.ctx = ARGC_LOG;
6782 curproxy->conf.args.file = curproxy->conf.lfs_file;
6783 curproxy->conf.args.line = curproxy->conf.lfs_line;
6784 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006785 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006786 curproxy->conf.args.file = NULL;
6787 curproxy->conf.args.line = 0;
6788 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006789
Willy Tarreau62a61232013-04-12 18:13:46 +02006790 if (curproxy->conf.uniqueid_format_string) {
6791 curproxy->conf.args.ctx = ARGC_UIF;
6792 curproxy->conf.args.file = curproxy->conf.uif_file;
6793 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006794 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08006795 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006796 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006797 curproxy->conf.args.file = NULL;
6798 curproxy->conf.args.line = 0;
6799 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006800
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006801 /* only now we can check if some args remain unresolved.
6802 * This must be done after the users and groups resolution.
6803 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006804 cfgerr += smp_resolve_args(curproxy);
6805 if (!cfgerr)
6806 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006807
Willy Tarreau2738a142006-07-08 17:28:09 +02006808 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006809 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006810 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006811 (!curproxy->timeout.connect ||
6812 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006813 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006814 " | While not properly invalid, you will certainly encounter various problems\n"
6815 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006816 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006817 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006818 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006819 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006820
Willy Tarreau1fa31262007-12-03 00:36:16 +01006821 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6822 * We must still support older configurations, so let's find out whether those
6823 * parameters have been set or must be copied from contimeouts.
6824 */
6825 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006826 if (!curproxy->timeout.tarpit ||
6827 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006828 /* tarpit timeout not set. We search in the following order:
6829 * default.tarpit, curr.connect, default.connect.
6830 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006831 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006832 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006833 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006834 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006835 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006836 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006837 }
6838 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006839 (!curproxy->timeout.queue ||
6840 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006841 /* queue timeout not set. We search in the following order:
6842 * default.queue, curr.connect, default.connect.
6843 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006844 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006845 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006846 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006847 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006848 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006849 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006850 }
6851 }
6852
Willy Tarreau1620ec32011-08-06 17:05:02 +02006853 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006854 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6855 curproxy->check_req = (char *)malloc(curproxy->check_len);
6856 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006857 }
6858
Willy Tarreau215663d2014-06-13 18:30:23 +02006859 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6860 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6861 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6862 proxy_type_str(curproxy), curproxy->id);
6863 err_code |= ERR_WARN;
6864 }
6865
Willy Tarreau193b8c62012-11-22 00:17:38 +01006866 /* ensure that cookie capture length is not too large */
6867 if (curproxy->capture_len >= global.tune.cookie_len) {
6868 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6869 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6870 err_code |= ERR_WARN;
6871 curproxy->capture_len = global.tune.cookie_len - 1;
6872 }
6873
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006874 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006875 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006876 curproxy->req_cap_pool = create_pool("ptrcap",
6877 curproxy->nb_req_cap * sizeof(char *),
6878 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006879 }
6880
6881 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006882 curproxy->rsp_cap_pool = create_pool("ptrcap",
6883 curproxy->nb_rsp_cap * sizeof(char *),
6884 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006885 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006886
Willy Tarreaubaaee002006-06-26 02:48:02 +02006887 /* first, we will invert the servers list order */
6888 newsrv = NULL;
6889 while (curproxy->srv) {
6890 struct server *next;
6891
6892 next = curproxy->srv->next;
6893 curproxy->srv->next = newsrv;
6894 newsrv = curproxy->srv;
6895 if (!next)
6896 break;
6897 curproxy->srv = next;
6898 }
6899
Willy Tarreau17edc812014-01-03 12:14:34 +01006900 /* Check that no server name conflicts. This causes trouble in the stats.
6901 * We only emit a warning for the first conflict affecting each server,
6902 * in order to avoid combinatory explosion if all servers have the same
6903 * name. We do that only for servers which do not have an explicit ID,
6904 * because these IDs were made also for distinguishing them and we don't
6905 * want to annoy people who correctly manage them.
6906 */
6907 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6908 struct server *other_srv;
6909
6910 if (newsrv->puid)
6911 continue;
6912
6913 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6914 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6915 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6916 newsrv->conf.file, newsrv->conf.line,
6917 proxy_type_str(curproxy), curproxy->id,
6918 newsrv->id, other_srv->conf.line);
6919 break;
6920 }
6921 }
6922 }
6923
Willy Tarreaudd701652010-05-25 23:03:02 +02006924 /* assign automatic UIDs to servers which don't have one yet */
6925 next_id = 1;
6926 newsrv = curproxy->srv;
6927 while (newsrv != NULL) {
6928 if (!newsrv->puid) {
6929 /* server ID not set, use automatic numbering with first
6930 * spare entry starting with next_svid.
6931 */
6932 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6933 newsrv->conf.id.key = newsrv->puid = next_id;
6934 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6935 }
6936 next_id++;
6937 newsrv = newsrv->next;
6938 }
6939
Willy Tarreau20697042007-11-15 23:26:18 +01006940 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006941 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006942
Willy Tarreau62c3be22012-01-20 13:12:32 +01006943 /*
6944 * If this server supports a maxconn parameter, it needs a dedicated
6945 * tasks to fill the emptied slots when a connection leaves.
6946 * Also, resolve deferred tracking dependency if needed.
6947 */
6948 newsrv = curproxy->srv;
6949 while (newsrv != NULL) {
6950 if (newsrv->minconn > newsrv->maxconn) {
6951 /* Only 'minconn' was specified, or it was higher than or equal
6952 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6953 * this will avoid further useless expensive computations.
6954 */
6955 newsrv->maxconn = newsrv->minconn;
6956 } else if (newsrv->maxconn && !newsrv->minconn) {
6957 /* minconn was not specified, so we set it to maxconn */
6958 newsrv->minconn = newsrv->maxconn;
6959 }
6960
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006961#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006962 if (newsrv->use_ssl || newsrv->check.use_ssl)
6963 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006964#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006965
Willy Tarreau2f075e92013-12-03 11:11:34 +01006966 /* set the check type on the server */
6967 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6968
Willy Tarreau62c3be22012-01-20 13:12:32 +01006969 if (newsrv->trackit) {
6970 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006971 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006972 char *pname, *sname;
6973
6974 pname = newsrv->trackit;
6975 sname = strrchr(pname, '/');
6976
6977 if (sname)
6978 *sname++ = '\0';
6979 else {
6980 sname = pname;
6981 pname = NULL;
6982 }
6983
6984 if (pname) {
6985 px = findproxy(pname, PR_CAP_BE);
6986 if (!px) {
6987 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6988 proxy_type_str(curproxy), curproxy->id,
6989 newsrv->id, pname);
6990 cfgerr++;
6991 goto next_srv;
6992 }
6993 } else
6994 px = curproxy;
6995
6996 srv = findserver(px, sname);
6997 if (!srv) {
6998 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6999 proxy_type_str(curproxy), curproxy->id,
7000 newsrv->id, sname);
7001 cfgerr++;
7002 goto next_srv;
7003 }
7004
Willy Tarreau32091232014-05-16 13:52:00 +02007005 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7006 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7007 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007008 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007009 "tracking as it does not have any check nor agent enabled.\n",
7010 proxy_type_str(curproxy), curproxy->id,
7011 newsrv->id, px->id, srv->id);
7012 cfgerr++;
7013 goto next_srv;
7014 }
7015
7016 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7017
7018 if (loop) {
7019 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7020 "belongs to a tracking chain looping back to %s/%s.\n",
7021 proxy_type_str(curproxy), curproxy->id,
7022 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007023 cfgerr++;
7024 goto next_srv;
7025 }
7026
7027 if (curproxy != px &&
7028 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7029 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7030 "tracking: disable-on-404 option inconsistency.\n",
7031 proxy_type_str(curproxy), curproxy->id,
7032 newsrv->id, px->id, srv->id);
7033 cfgerr++;
7034 goto next_srv;
7035 }
7036
7037 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007038 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007039 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007040 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007041 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007042 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007043 }
7044
7045 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007046 newsrv->tracknext = srv->trackers;
7047 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007048
7049 free(newsrv->trackit);
7050 newsrv->trackit = NULL;
7051 }
7052 next_srv:
7053 newsrv = newsrv->next;
7054 }
7055
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007056 /* We have to initialize the server lookup mechanism depending
7057 * on what LB algorithm was choosen.
7058 */
7059
7060 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7061 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7062 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007063 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7064 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7065 init_server_map(curproxy);
7066 } else {
7067 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7068 fwrr_init_server_groups(curproxy);
7069 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007070 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007071
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007072 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007073 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7074 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7075 fwlc_init_server_tree(curproxy);
7076 } else {
7077 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7078 fas_init_server_tree(curproxy);
7079 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007080 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007081
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007082 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007083 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7084 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7085 chash_init_server_tree(curproxy);
7086 } else {
7087 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7088 init_server_map(curproxy);
7089 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007090 break;
7091 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007092
7093 if (curproxy->options & PR_O_LOGASAP)
7094 curproxy->to_log &= ~LW_BYTES;
7095
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007096 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007097 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007098 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7099 proxy_type_str(curproxy), curproxy->id);
7100 err_code |= ERR_WARN;
7101 }
7102
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007103 if (curproxy->mode != PR_MODE_HTTP) {
7104 int optnum;
7105
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007106 if (curproxy->uri_auth) {
7107 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7108 proxy_type_str(curproxy), curproxy->id);
7109 err_code |= ERR_WARN;
7110 curproxy->uri_auth = NULL;
7111 }
7112
Willy Tarreau87cf5142011-08-19 22:57:24 +02007113 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007114 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7115 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7116 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007117 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007118 }
7119
7120 if (curproxy->options & PR_O_ORGTO) {
7121 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7122 "originalto", proxy_type_str(curproxy), curproxy->id);
7123 err_code |= ERR_WARN;
7124 curproxy->options &= ~PR_O_ORGTO;
7125 }
7126
7127 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7128 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7129 (curproxy->cap & cfg_opts[optnum].cap) &&
7130 (curproxy->options & cfg_opts[optnum].val)) {
7131 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7132 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7133 err_code |= ERR_WARN;
7134 curproxy->options &= ~cfg_opts[optnum].val;
7135 }
7136 }
7137
7138 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7139 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7140 (curproxy->cap & cfg_opts2[optnum].cap) &&
7141 (curproxy->options2 & cfg_opts2[optnum].val)) {
7142 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7143 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7144 err_code |= ERR_WARN;
7145 curproxy->options2 &= ~cfg_opts2[optnum].val;
7146 }
7147 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007148
Pieter Baauwd551fb52013-05-08 22:49:23 +02007149#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007150 if (curproxy->conn_src.bind_hdr_occ) {
7151 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007152 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007153 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007154 err_code |= ERR_WARN;
7155 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007156#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007157 }
7158
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007160 * ensure that we're not cross-dressing a TCP server into HTTP.
7161 */
7162 newsrv = curproxy->srv;
7163 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007164 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007165 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7166 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007167 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007168 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007169
Willy Tarreau0cec3312011-10-31 13:49:26 +01007170 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7171 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7172 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7173 err_code |= ERR_WARN;
7174 }
7175
Willy Tarreauc93cd162014-05-13 15:54:22 +02007176 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007177 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7178 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7179 err_code |= ERR_WARN;
7180 }
7181
Pieter Baauwd551fb52013-05-08 22:49:23 +02007182#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007183 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7184 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007185 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 +01007186 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007187 err_code |= ERR_WARN;
7188 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007189#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007190 newsrv = newsrv->next;
7191 }
7192
Willy Tarreaue42bd962014-09-16 16:21:19 +02007193 /* check if we have a frontend with "tcp-request content" looking at L7
7194 * with no inspect-delay
7195 */
7196 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7197 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7198 if (trule->action == TCP_ACT_CAPTURE &&
7199 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7200 break;
7201 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7202 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7203 break;
7204 }
7205
7206 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7207 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7208 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7209 " This means that these rules will randomly find their contents. This can be fixed by"
7210 " setting the tcp-request inspect-delay.\n",
7211 proxy_type_str(curproxy), curproxy->id);
7212 err_code |= ERR_WARN;
7213 }
7214 }
7215
Willy Tarreauc1a21672009-08-16 22:37:44 +02007216 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007217 if (!curproxy->accept)
7218 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007219
Willy Tarreauc1a21672009-08-16 22:37:44 +02007220 if (curproxy->tcp_req.inspect_delay ||
7221 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007222 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007223
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007224 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007225 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007226 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007227 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007228
7229 /* both TCP and HTTP must check switching rules */
7230 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7231 }
7232
7233 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007234 if (curproxy->tcp_req.inspect_delay ||
7235 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7236 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7237
Emeric Brun97679e72010-09-23 17:56:44 +02007238 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7239 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7240
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007241 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007242 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007243 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007244 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007245
7246 /* If the backend does requires RDP cookie persistence, we have to
7247 * enable the corresponding analyser.
7248 */
7249 if (curproxy->options2 & PR_O2_RDPC_PRST)
7250 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7251 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007252 }
7253
7254 /***********************************************************/
7255 /* At this point, target names have already been resolved. */
7256 /***********************************************************/
7257
7258 /* Check multi-process mode compatibility */
7259
7260 if (global.nbproc > 1 && global.stats_fe) {
7261 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7262 unsigned long mask;
7263
7264 mask = nbits(global.nbproc);
7265 if (global.stats_fe->bind_proc)
7266 mask &= global.stats_fe->bind_proc;
7267
7268 if (bind_conf->bind_proc)
7269 mask &= bind_conf->bind_proc;
7270
7271 /* stop here if more than one process is used */
7272 if (popcount(mask) > 1)
7273 break;
7274 }
7275 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7276 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");
7277 }
7278 }
7279
7280 /* Make each frontend inherit bind-process from its listeners when not specified. */
7281 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7282 if (curproxy->bind_proc)
7283 continue;
7284
7285 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7286 unsigned long mask;
7287
7288 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7289 curproxy->bind_proc |= mask;
7290 }
7291
7292 if (!curproxy->bind_proc)
7293 curproxy->bind_proc = ~0UL;
7294 }
7295
7296 if (global.stats_fe) {
7297 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7298 unsigned long mask;
7299
7300 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7301 global.stats_fe->bind_proc |= mask;
7302 }
7303 if (!global.stats_fe->bind_proc)
7304 global.stats_fe->bind_proc = ~0UL;
7305 }
7306
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007307 /* propagate bindings from frontends to backends. Don't do it if there
7308 * are any fatal errors as we must not call it with unresolved proxies.
7309 */
7310 if (!cfgerr) {
7311 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7312 if (curproxy->cap & PR_CAP_FE)
7313 propagate_processes(curproxy, NULL);
7314 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007315 }
7316
7317 /* Bind each unbound backend to all processes when not specified. */
7318 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7319 if (curproxy->bind_proc)
7320 continue;
7321 curproxy->bind_proc = ~0UL;
7322 }
7323
7324 /*******************************************************/
7325 /* At this step, all proxies have a non-null bind_proc */
7326 /*******************************************************/
7327
7328 /* perform the final checks before creating tasks */
7329
7330 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7331 struct listener *listener;
7332 unsigned int next_id;
7333 int nbproc;
7334
7335 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007336
Emeric Brunc52962f2012-11-15 18:28:02 +01007337#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007338 /* Configure SSL for each bind line.
7339 * Note: if configuration fails at some point, the ->ctx member
7340 * remains NULL so that listeners can later detach.
7341 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007342 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007343 int alloc_ctx;
7344
Emeric Brunc52962f2012-11-15 18:28:02 +01007345 if (!bind_conf->is_ssl) {
7346 if (bind_conf->default_ctx) {
7347 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7348 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7349 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007350 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007351 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007352 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007353 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007354 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007355 cfgerr++;
7356 continue;
7357 }
7358
Emeric Brun8dc60392014-05-09 13:52:00 +02007359 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007360 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007361 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7362 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");
7363 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007364 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007365 cfgerr++;
7366 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007367 }
7368
Emeric Brunfc0421f2012-09-07 17:30:07 +02007369 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007370 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007371 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007372#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007373
Willy Tarreaue6b98942007-10-29 01:09:36 +01007374 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007375 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007376 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007377 if (!listener->luid) {
7378 /* listener ID not set, use automatic numbering with first
7379 * spare entry starting with next_luid.
7380 */
7381 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7382 listener->conf.id.key = listener->luid = next_id;
7383 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007384 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007385 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007386
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007387 /* enable separate counters */
7388 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7389 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007390 if (!listener->name)
7391 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007392 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007393
Willy Tarreaue6b98942007-10-29 01:09:36 +01007394 if (curproxy->options & PR_O_TCP_NOLING)
7395 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007396 if (!listener->maxconn)
7397 listener->maxconn = curproxy->maxconn;
7398 if (!listener->backlog)
7399 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007400 if (!listener->maxaccept)
7401 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7402
7403 /* we want to have an optimal behaviour on single process mode to
7404 * maximize the work at once, but in multi-process we want to keep
7405 * some fairness between processes, so we target half of the max
7406 * number of events to be balanced over all the processes the proxy
7407 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7408 * used to disable the limit.
7409 */
7410 if (listener->maxaccept > 0) {
7411 if (nbproc > 1)
7412 listener->maxaccept = (listener->maxaccept + 1) / 2;
7413 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7414 }
7415
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007416 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007417 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007418 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007419 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007420
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007421 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7422 listener->options |= LI_O_TCP_RULES;
7423
Willy Tarreaude3041d2010-05-31 10:56:17 +02007424 if (curproxy->mon_mask.s_addr)
7425 listener->options |= LI_O_CHK_MONNET;
7426
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007427 /* smart accept mode is automatic in HTTP mode */
7428 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007429 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007430 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7431 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007432 }
7433
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007434 /* Release unused SSL configs */
7435 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7436 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007437 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007438#ifdef USE_OPENSSL
7439 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007440 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007441 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007442 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007443 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007444#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007445 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007446
Willy Tarreau102df612014-05-07 23:56:38 +02007447 if (nbproc > 1) {
7448 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007449 int count, maxproc = 0;
7450
7451 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7452 count = popcount(bind_conf->bind_proc);
7453 if (count > maxproc)
7454 maxproc = count;
7455 }
7456 /* backends have 0, frontends have 1 or more */
7457 if (maxproc != 1)
7458 Warning("Proxy '%s': in multi-process mode, stats will be"
7459 " limited to process assigned to the current request.\n",
7460 curproxy->id);
7461
Willy Tarreau102df612014-05-07 23:56:38 +02007462 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7463 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7464 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007465 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007466 }
Willy Tarreau102df612014-05-07 23:56:38 +02007467 if (curproxy->appsession_name) {
7468 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7469 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007470 }
Willy Tarreau102df612014-05-07 23:56:38 +02007471 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7472 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7473 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007474 }
7475 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007476
7477 /* create the task associated with the proxy */
7478 curproxy->task = task_new();
7479 if (curproxy->task) {
7480 curproxy->task->context = curproxy;
7481 curproxy->task->process = manage_proxy;
7482 /* no need to queue, it will be done automatically if some
7483 * listener gets limited.
7484 */
7485 curproxy->task->expire = TICK_ETERNITY;
7486 } else {
7487 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7488 curproxy->id);
7489 cfgerr++;
7490 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007491 }
7492
Willy Tarreaufbb78422011-06-05 15:38:35 +02007493 /* automatically compute fullconn if not set. We must not do it in the
7494 * loop above because cross-references are not yet fully resolved.
7495 */
7496 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7497 /* If <fullconn> is not set, let's set it to 10% of the sum of
7498 * the possible incoming frontend's maxconns.
7499 */
7500 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7501 struct proxy *fe;
7502 int total = 0;
7503
7504 /* sum up the number of maxconns of frontends which
7505 * reference this backend at least once or which are
7506 * the same one ('listen').
7507 */
7508 for (fe = proxy; fe; fe = fe->next) {
7509 struct switching_rule *rule;
7510 struct hdr_exp *exp;
7511 int found = 0;
7512
7513 if (!(fe->cap & PR_CAP_FE))
7514 continue;
7515
7516 if (fe == curproxy) /* we're on a "listen" instance */
7517 found = 1;
7518
7519 if (fe->defbe.be == curproxy) /* "default_backend" */
7520 found = 1;
7521
7522 /* check if a "use_backend" rule matches */
7523 if (!found) {
7524 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007525 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007526 found = 1;
7527 break;
7528 }
7529 }
7530 }
7531
7532 /* check if a "reqsetbe" rule matches */
7533 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7534 if (exp->action == ACT_SETBE &&
7535 (struct proxy *)exp->replace == curproxy) {
7536 found = 1;
7537 break;
7538 }
7539 }
7540
7541 /* now we've checked all possible ways to reference a backend
7542 * from a frontend.
7543 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007544 if (!found)
7545 continue;
7546 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007547 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007548 /* we have the sum of the maxconns in <total>. We only
7549 * keep 10% of that sum to set the default fullconn, with
7550 * a hard minimum of 1 (to avoid a divide by zero).
7551 */
7552 curproxy->fullconn = (total + 9) / 10;
7553 if (!curproxy->fullconn)
7554 curproxy->fullconn = 1;
7555 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007556 }
7557
Willy Tarreau056f5682010-06-06 15:51:11 +02007558 /* initialize stick-tables on backend capable proxies. This must not
7559 * be done earlier because the data size may be discovered while parsing
7560 * other proxies.
7561 */
Godbach9703e662013-12-11 21:11:41 +08007562 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007563 if (curproxy->state == PR_STSTOPPED)
7564 continue;
7565
Godbach9703e662013-12-11 21:11:41 +08007566 if (!stktable_init(&curproxy->table)) {
7567 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7568 cfgerr++;
7569 }
7570 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007571
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007572 /*
7573 * Recount currently required checks.
7574 */
7575
7576 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7577 int optnum;
7578
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007579 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7580 if (curproxy->options & cfg_opts[optnum].val)
7581 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007582
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007583 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7584 if (curproxy->options2 & cfg_opts2[optnum].val)
7585 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007586 }
7587
Willy Tarreau122541c2011-09-07 21:24:49 +02007588 if (peers) {
7589 struct peers *curpeers = peers, **last;
7590 struct peer *p, *pb;
7591
7592 /* Remove all peers sections which don't have a valid listener.
7593 * This can happen when a peers section is never referenced and
7594 * does not contain a local peer.
7595 */
7596 last = &peers;
7597 while (*last) {
7598 curpeers = *last;
7599 if (curpeers->peers_fe) {
7600 last = &curpeers->next;
7601 continue;
7602 }
7603
7604 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7605 curpeers->id, localpeer);
7606
7607 p = curpeers->remote;
7608 while (p) {
7609 pb = p->next;
7610 free(p->id);
7611 free(p);
7612 p = pb;
7613 }
7614
7615 /* Destroy and unlink this curpeers section.
7616 * Note: curpeers is backed up into *last.
7617 */
7618 free(curpeers->id);
7619 curpeers = curpeers->next;
7620 free(*last);
7621 *last = curpeers;
7622 }
7623 }
7624
Willy Tarreau34eb6712011-10-24 18:15:04 +02007625 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007626 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007627 MEM_F_SHARED);
7628
Willy Tarreaubb925012009-07-23 13:36:36 +02007629 if (cfgerr > 0)
7630 err_code |= ERR_ALERT | ERR_FATAL;
7631 out:
7632 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007633}
7634
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007635/*
7636 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7637 * parsing sessions.
7638 */
7639void cfg_register_keywords(struct cfg_kw_list *kwl)
7640{
7641 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7642}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007643
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007644/*
7645 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7646 */
7647void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7648{
7649 LIST_DEL(&kwl->list);
7650 LIST_INIT(&kwl->list);
7651}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007652
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007653/* this function register new section in the haproxy configuration file.
7654 * <section_name> is the name of this new section and <section_parser>
7655 * is the called parser. If two section declaration have the same name,
7656 * only the first declared is used.
7657 */
7658int cfg_register_section(char *section_name,
7659 int (*section_parser)(const char *, int, char **, int))
7660{
7661 struct cfg_section *cs;
7662
7663 cs = calloc(1, sizeof(*cs));
7664 if (!cs) {
7665 Alert("register section '%s': out of memory.\n", section_name);
7666 return 0;
7667 }
7668
7669 cs->section_name = section_name;
7670 cs->section_parser = section_parser;
7671
7672 LIST_ADDQ(&sections, &cs->list);
7673
7674 return 1;
7675}
7676
Willy Tarreaubaaee002006-06-26 02:48:02 +02007677/*
7678 * Local variables:
7679 * c-indent-level: 8
7680 * c-basic-offset: 8
7681 * End:
7682 */