blob: fe5d24ae2f5c724796a695b407d291c848ccd431 [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 Tarreau33cb0652014-12-23 22:52:37 +0100699 else if (!strcmp(args[0], "tune.buffers.limit")) {
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.buf_limit = atol(args[1]);
706 if (global.tune.buf_limit) {
707 if (global.tune.buf_limit < 3)
708 global.tune.buf_limit = 3;
709 if (global.tune.buf_limit <= global.tune.reserved_bufs)
710 global.tune.buf_limit = global.tune.reserved_bufs + 1;
711 }
712 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100713 else if (!strcmp(args[0], "tune.buffers.reserve")) {
714 if (*(args[1]) == 0) {
715 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
716 err_code |= ERR_ALERT | ERR_FATAL;
717 goto out;
718 }
719 global.tune.reserved_bufs = atol(args[1]);
720 if (global.tune.reserved_bufs < 2)
721 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100722 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
723 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100724 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200725 else if (!strcmp(args[0], "tune.bufsize")) {
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
730 }
731 global.tune.bufsize = atol(args[1]);
732 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
733 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100734 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100735 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200736 }
737 else if (!strcmp(args[0], "tune.maxrewrite")) {
738 if (*(args[1]) == 0) {
739 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743 global.tune.maxrewrite = atol(args[1]);
744 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
745 global.tune.maxrewrite = global.tune.bufsize / 2;
746 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100747 else if (!strcmp(args[0], "tune.idletimer")) {
748 unsigned int idle;
749 const char *res;
750
751 if (*(args[1]) == 0) {
752 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
753 err_code |= ERR_ALERT | ERR_FATAL;
754 goto out;
755 }
756
757 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
758 if (res) {
759 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
760 file, linenum, *res, args[0]);
761 err_code |= ERR_ALERT | ERR_FATAL;
762 goto out;
763 }
764
765 if (idle > 65535) {
766 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.idle_timer = idle;
771 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100772 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
773 if (global.tune.client_rcvbuf != 0) {
774 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT;
776 goto out;
777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.client_rcvbuf = atol(args[1]);
784 }
785 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
786 if (global.tune.server_rcvbuf != 0) {
787 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT;
789 goto out;
790 }
791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.tune.server_rcvbuf = atol(args[1]);
797 }
798 else if (!strcmp(args[0], "tune.sndbuf.client")) {
799 if (global.tune.client_sndbuf != 0) {
800 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT;
802 goto out;
803 }
804 if (*(args[1]) == 0) {
805 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
806 err_code |= ERR_ALERT | ERR_FATAL;
807 goto out;
808 }
809 global.tune.client_sndbuf = atol(args[1]);
810 }
811 else if (!strcmp(args[0], "tune.sndbuf.server")) {
812 if (global.tune.server_sndbuf != 0) {
813 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT;
815 goto out;
816 }
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.server_sndbuf = atol(args[1]);
823 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200824 else if (!strcmp(args[0], "tune.pipesize")) {
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.pipesize = atol(args[1]);
831 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100832 else if (!strcmp(args[0], "tune.http.cookielen")) {
833 if (*(args[1]) == 0) {
834 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838 global.tune.cookie_len = atol(args[1]) + 1;
839 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200840 else if (!strcmp(args[0], "tune.http.maxhdr")) {
841 if (*(args[1]) == 0) {
842 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
843 err_code |= ERR_ALERT | ERR_FATAL;
844 goto out;
845 }
846 global.tune.max_http_hdr = atol(args[1]);
847 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100848 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
849#ifdef USE_ZLIB
850 if (*args[1]) {
851 global.tune.zlibmemlevel = atoi(args[1]);
852 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
853 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
854 file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858 } else {
859 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\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' is not implemented.\n", file, linenum, args[0]);
866 err_code |= ERR_ALERT | ERR_FATAL;
867 goto out;
868#endif
869 }
870 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
871#ifdef USE_ZLIB
872 if (*args[1]) {
873 global.tune.zlibwindowsize = atoi(args[1]);
874 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 } else {
881 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
882 file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886#else
887 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890#endif
891 }
William Lallemandf3747832012-11-09 12:33:10 +0100892 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
893 if (*args[1]) {
894 global.tune.comp_maxlevel = atoi(args[1]);
895 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
896 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
897 file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901 } else {
902 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
903 file, linenum, args[0]);
904 err_code |= ERR_ALERT | ERR_FATAL;
905 goto out;
906 }
907 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200908 else if (!strcmp(args[0], "uid")) {
909 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200910 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200911 err_code |= ERR_ALERT;
912 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200913 }
914 if (*(args[1]) == 0) {
915 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200916 err_code |= ERR_ALERT | ERR_FATAL;
917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200918 }
919 global.uid = atol(args[1]);
920 }
921 else if (!strcmp(args[0], "gid")) {
922 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200923 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200924 err_code |= ERR_ALERT;
925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200926 }
927 if (*(args[1]) == 0) {
928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200931 }
932 global.gid = atol(args[1]);
933 }
Simon Horman98637e52014-06-20 12:30:16 +0900934 else if (!strcmp(args[0], "external-check")) {
935 global.external_check = 1;
936 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200937 /* user/group name handling */
938 else if (!strcmp(args[0], "user")) {
939 struct passwd *ha_user;
940 if (global.uid != 0) {
941 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200942 err_code |= ERR_ALERT;
943 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200944 }
945 errno = 0;
946 ha_user = getpwnam(args[1]);
947 if (ha_user != NULL) {
948 global.uid = (int)ha_user->pw_uid;
949 }
950 else {
951 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 +0200952 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200953 }
954 }
955 else if (!strcmp(args[0], "group")) {
956 struct group *ha_group;
957 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200958 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200959 err_code |= ERR_ALERT;
960 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200961 }
962 errno = 0;
963 ha_group = getgrnam(args[1]);
964 if (ha_group != NULL) {
965 global.gid = (int)ha_group->gr_gid;
966 }
967 else {
968 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 +0200969 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200970 }
971 }
972 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 if (*(args[1]) == 0) {
975 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200976 err_code |= ERR_ALERT | ERR_FATAL;
977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200978 }
979 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100980 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
981 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
982 file, linenum, args[0], LONGBITS, global.nbproc);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200986 }
987 else if (!strcmp(args[0], "maxconn")) {
988 if (global.maxconn != 0) {
989 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200990 err_code |= ERR_ALERT;
991 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200992 }
993 if (*(args[1]) == 0) {
994 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200995 err_code |= ERR_ALERT | ERR_FATAL;
996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200997 }
998 global.maxconn = atol(args[1]);
999#ifdef SYSTEM_MAXCONN
1000 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1001 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);
1002 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001003 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001004 }
1005#endif /* SYSTEM_MAXCONN */
1006 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001007 else if (!strcmp(args[0], "maxsslconn")) {
1008#ifdef USE_OPENSSL
1009 if (*(args[1]) == 0) {
1010 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 global.maxsslconn = atol(args[1]);
1015#else
Emeric Brun0914df82012-10-02 18:45:42 +02001016 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001019#endif
1020 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001021 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1022#ifdef USE_OPENSSL
1023 if (*(args[1]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 free(global.listen_default_ciphers);
1029 global.listen_default_ciphers = strdup(args[1]);
1030#else
1031 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
1034#endif
1035 }
1036 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1037#ifdef USE_OPENSSL
1038 if (*(args[1]) == 0) {
1039 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1040 err_code |= ERR_ALERT | ERR_FATAL;
1041 goto out;
1042 }
1043 free(global.connect_default_ciphers);
1044 global.connect_default_ciphers = strdup(args[1]);
1045#else
1046 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049#endif
1050 }
Emeric Brun850efd52014-01-29 12:24:34 +01001051 else if (!strcmp(args[0], "ssl-server-verify")) {
1052 if (*(args[1]) == 0) {
1053 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1054 err_code |= ERR_ALERT | ERR_FATAL;
1055 goto out;
1056 }
1057 if (strcmp(args[1],"none") == 0)
1058 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1059 else if (strcmp(args[1],"required") == 0)
1060 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1061 else {
1062 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1063 err_code |= ERR_ALERT | ERR_FATAL;
1064 goto out;
1065 }
1066 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001067 else if (!strcmp(args[0], "maxconnrate")) {
1068 if (global.cps_lim != 0) {
1069 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1070 err_code |= ERR_ALERT;
1071 goto out;
1072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
1077 }
1078 global.cps_lim = atol(args[1]);
1079 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001080 else if (!strcmp(args[0], "maxsessrate")) {
1081 if (global.sps_lim != 0) {
1082 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1083 err_code |= ERR_ALERT;
1084 goto out;
1085 }
1086 if (*(args[1]) == 0) {
1087 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1088 err_code |= ERR_ALERT | ERR_FATAL;
1089 goto out;
1090 }
1091 global.sps_lim = atol(args[1]);
1092 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001093 else if (!strcmp(args[0], "maxsslrate")) {
1094 if (global.ssl_lim != 0) {
1095 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1096 err_code |= ERR_ALERT;
1097 goto out;
1098 }
1099 if (*(args[1]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
1104 global.ssl_lim = atol(args[1]);
1105 }
William Lallemandd85f9172012-11-09 17:05:39 +01001106 else if (!strcmp(args[0], "maxcomprate")) {
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 global.comp_rate_lim = atoi(args[1]) * 1024;
1113 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001114 else if (!strcmp(args[0], "maxpipes")) {
1115 if (global.maxpipes != 0) {
1116 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT;
1118 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001119 }
1120 if (*(args[1]) == 0) {
1121 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001122 err_code |= ERR_ALERT | ERR_FATAL;
1123 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001124 }
1125 global.maxpipes = atol(args[1]);
1126 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001127 else if (!strcmp(args[0], "maxzlibmem")) {
1128 if (*(args[1]) == 0) {
1129 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1130 err_code |= ERR_ALERT | ERR_FATAL;
1131 goto out;
1132 }
William Lallemande3a7d992012-11-20 11:25:20 +01001133 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001134 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001135 else if (!strcmp(args[0], "maxcompcpuusage")) {
1136 if (*(args[1]) == 0) {
1137 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto out;
1140 }
1141 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001142 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001143 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1144 err_code |= ERR_ALERT | ERR_FATAL;
1145 goto out;
1146 }
1147}
1148
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 else if (!strcmp(args[0], "ulimit-n")) {
1150 if (global.rlimit_nofile != 0) {
1151 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001152 err_code |= ERR_ALERT;
1153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001154 }
1155 if (*(args[1]) == 0) {
1156 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 }
1160 global.rlimit_nofile = atol(args[1]);
1161 }
1162 else if (!strcmp(args[0], "chroot")) {
1163 if (global.chroot != NULL) {
1164 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001165 err_code |= ERR_ALERT;
1166 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001167 }
1168 if (*(args[1]) == 0) {
1169 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 global.chroot = strdup(args[1]);
1174 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001175 else if (!strcmp(args[0], "description")) {
1176 int i, len=0;
1177 char *d;
1178
1179 if (!*args[1]) {
1180 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1181 file, linenum, args[0]);
1182 err_code |= ERR_ALERT | ERR_FATAL;
1183 goto out;
1184 }
1185
Willy Tarreau348acfe2014-04-14 15:00:39 +02001186 for (i = 1; *args[i]; i++)
1187 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001188
1189 if (global.desc)
1190 free(global.desc);
1191
1192 global.desc = d = (char *)calloc(1, len);
1193
Willy Tarreau348acfe2014-04-14 15:00:39 +02001194 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1195 for (i = 2; *args[i]; i++)
1196 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001197 }
1198 else if (!strcmp(args[0], "node")) {
1199 int i;
1200 char c;
1201
1202 for (i=0; args[1][i]; i++) {
1203 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001204 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1205 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001206 break;
1207 }
1208
1209 if (!i || args[1][i]) {
1210 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1211 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1212 file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216
1217 if (global.node)
1218 free(global.node);
1219
1220 global.node = strdup(args[1]);
1221 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001222 else if (!strcmp(args[0], "pidfile")) {
1223 if (global.pidfile != NULL) {
1224 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001225 err_code |= ERR_ALERT;
1226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001227 }
1228 if (*(args[1]) == 0) {
1229 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001232 }
1233 global.pidfile = strdup(args[1]);
1234 }
Emeric Bruned760922010-10-22 17:59:25 +02001235 else if (!strcmp(args[0], "unix-bind")) {
1236 int cur_arg = 1;
1237 while (*(args[cur_arg])) {
1238 if (!strcmp(args[cur_arg], "prefix")) {
1239 if (global.unix_bind.prefix != NULL) {
1240 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1241 err_code |= ERR_ALERT;
1242 cur_arg += 2;
1243 continue;
1244 }
1245
1246 if (*(args[cur_arg+1]) == 0) {
1247 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1248 err_code |= ERR_ALERT | ERR_FATAL;
1249 goto out;
1250 }
1251 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1252 cur_arg += 2;
1253 continue;
1254 }
1255
1256 if (!strcmp(args[cur_arg], "mode")) {
1257
1258 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1259 cur_arg += 2;
1260 continue;
1261 }
1262
1263 if (!strcmp(args[cur_arg], "uid")) {
1264
1265 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1266 cur_arg += 2;
1267 continue;
1268 }
1269
1270 if (!strcmp(args[cur_arg], "gid")) {
1271
1272 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1273 cur_arg += 2;
1274 continue;
1275 }
1276
1277 if (!strcmp(args[cur_arg], "user")) {
1278 struct passwd *user;
1279
1280 user = getpwnam(args[cur_arg + 1]);
1281 if (!user) {
1282 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\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.uid = user->pw_uid;
1289 cur_arg += 2;
1290 continue;
1291 }
1292
1293 if (!strcmp(args[cur_arg], "group")) {
1294 struct group *group;
1295
1296 group = getgrnam(args[cur_arg + 1]);
1297 if (!group) {
1298 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1299 file, linenum, args[0], args[cur_arg + 1 ]);
1300 err_code |= ERR_ALERT | ERR_FATAL;
1301 goto out;
1302 }
1303
1304 global.unix_bind.ux.gid = group->gr_gid;
1305 cur_arg += 2;
1306 continue;
1307 }
1308
Willy Tarreaub48f9582011-09-05 01:17:06 +02001309 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001310 file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 }
William Lallemand0f99e342011-10-12 17:50:54 +02001315 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1316 /* delete previous herited or defined syslog servers */
1317 struct logsrv *back;
1318 struct logsrv *tmp;
1319
1320 if (*(args[1]) != 0) {
1321 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1322 err_code |= ERR_ALERT | ERR_FATAL;
1323 goto out;
1324 }
1325
1326 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1327 LIST_DEL(&tmp->list);
1328 free(tmp);
1329 }
1330 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001331 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001332 struct sockaddr_storage *sk;
1333 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001334 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001335 int arg = 0;
1336 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001337
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 if (*(args[1]) == 0 || *(args[2]) == 0) {
1339 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001340 err_code |= ERR_ALERT | ERR_FATAL;
1341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 }
William Lallemand0f99e342011-10-12 17:50:54 +02001343
1344 logsrv = calloc(1, sizeof(struct logsrv));
1345
Willy Tarreau18324f52014-06-27 18:10:07 +02001346 /* just after the address, a length may be specified */
1347 if (strcmp(args[arg+2], "len") == 0) {
1348 len = atoi(args[arg+3]);
1349 if (len < 80 || len > 65535) {
1350 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1351 file, linenum, args[arg+3]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 logsrv->maxlen = len;
1356
1357 /* skip these two args */
1358 arg += 2;
1359 }
1360 else
1361 logsrv->maxlen = MAX_SYSLOG_LEN;
1362
1363 if (logsrv->maxlen > global.max_syslog_len) {
1364 global.max_syslog_len = logsrv->maxlen;
1365 logline = realloc(logline, global.max_syslog_len + 1);
1366 }
1367
1368 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001369 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001370 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001372 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001373 }
1374
William Lallemand0f99e342011-10-12 17:50:54 +02001375 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001376 if (*(args[arg+3])) {
1377 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001378 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001379 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001380 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001381 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001382 }
1383 }
1384
William Lallemand0f99e342011-10-12 17:50:54 +02001385 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001386 if (*(args[arg+4])) {
1387 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001388 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001389 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001390 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001391 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001392 }
1393 }
1394
Willy Tarreau902636f2013-03-10 19:44:48 +01001395 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001396 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001397 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001398 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001399 free(logsrv);
1400 goto out;
1401 }
1402 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001403
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001404 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001405 if (port1 != port2) {
1406 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1407 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001408 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001409 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001410 goto out;
1411 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001412
William Lallemand0f99e342011-10-12 17:50:54 +02001413 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001414 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001415 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001416 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001417
William Lallemand0f99e342011-10-12 17:50:54 +02001418 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001419 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001420 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1421 char *name;
1422 int len;
1423
1424 if (global.log_send_hostname != NULL) {
1425 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1426 err_code |= ERR_ALERT;
1427 goto out;
1428 }
1429
1430 if (*(args[1]))
1431 name = args[1];
1432 else
1433 name = hostname;
1434
1435 len = strlen(name);
1436
1437 /* We'll add a space after the name to respect the log format */
1438 free(global.log_send_hostname);
1439 global.log_send_hostname = malloc(len + 2);
1440 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1441 }
Kevinm48936af2010-12-22 16:08:21 +00001442 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1443 if (*(args[1]) == 0) {
1444 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1445 err_code |= ERR_ALERT | ERR_FATAL;
1446 goto out;
1447 }
1448 free(global.log_tag);
1449 global.log_tag = strdup(args[1]);
1450 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001451 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1452 if (global.spread_checks != 0) {
1453 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001454 err_code |= ERR_ALERT;
1455 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001456 }
1457 if (*(args[1]) == 0) {
1458 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001459 err_code |= ERR_ALERT | ERR_FATAL;
1460 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001461 }
1462 global.spread_checks = atol(args[1]);
1463 if (global.spread_checks < 0 || global.spread_checks > 50) {
1464 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001465 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001466 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001467 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001468 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1469 const char *err;
1470 unsigned int val;
1471
1472
1473 if (*(args[1]) == 0) {
1474 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
1477 }
1478
1479 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1480 if (err) {
1481 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 }
1484 global.max_spread_checks = val;
1485 if (global.max_spread_checks < 0) {
1486 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1487 err_code |= ERR_ALERT | ERR_FATAL;
1488 }
1489 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001490 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1491#ifdef USE_CPU_AFFINITY
1492 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001493 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001494 unsigned long cpus = 0;
1495
1496 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001497 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001498 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001499 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001500 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001501 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001502 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001503 proc = atol(args[1]);
1504 if (proc >= 1 && proc <= LONGBITS)
1505 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001506 }
1507
1508 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001509 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",
1510 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 cur_arg = 2;
1516 while (*args[cur_arg]) {
1517 unsigned int low, high;
1518
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001519 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001520 char *dash = strchr(args[cur_arg], '-');
1521
1522 low = high = str2uic(args[cur_arg]);
1523 if (dash)
1524 high = str2uic(dash + 1);
1525
1526 if (high < low) {
1527 unsigned int swap = low;
1528 low = high;
1529 high = swap;
1530 }
1531
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001532 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001533 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001534 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001535 err_code |= ERR_ALERT | ERR_FATAL;
1536 goto out;
1537 }
1538
1539 while (low <= high)
1540 cpus |= 1UL << low++;
1541 }
1542 else {
1543 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1544 file, linenum, args[0], args[cur_arg]);
1545 err_code |= ERR_ALERT | ERR_FATAL;
1546 goto out;
1547 }
1548 cur_arg++;
1549 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001550 for (i = 0; i < LONGBITS; i++)
1551 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001552 global.cpu_map[i] = cpus;
1553#else
1554 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1555 err_code |= ERR_ALERT | ERR_FATAL;
1556 goto out;
1557#endif
1558 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001560 struct cfg_kw_list *kwl;
1561 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001562 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001563
1564 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1565 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1566 if (kwl->kw[index].section != CFG_GLOBAL)
1567 continue;
1568 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001569 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001570 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001571 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001572 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001573 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001574 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001575 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_WARN;
1577 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001578 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001579 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001580 }
1581 }
1582 }
1583
Willy Tarreaubaaee002006-06-26 02:48:02 +02001584 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001587
Willy Tarreau058e9072009-07-20 09:30:05 +02001588 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001589 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001590 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591}
1592
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001593void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001594{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001595 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001596 defproxy.mode = PR_MODE_TCP;
1597 defproxy.state = PR_STNEW;
1598 defproxy.maxconn = cfg_maxpconn;
1599 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001600
Simon Horman66183002013-02-23 10:16:43 +09001601 defproxy.defsrv.check.inter = DEF_CHKINTR;
1602 defproxy.defsrv.check.fastinter = 0;
1603 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001604 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1605 defproxy.defsrv.agent.fastinter = 0;
1606 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001607 defproxy.defsrv.check.rise = DEF_RISETIME;
1608 defproxy.defsrv.check.fall = DEF_FALLTIME;
1609 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1610 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001611 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001612 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001613 defproxy.defsrv.maxqueue = 0;
1614 defproxy.defsrv.minconn = 0;
1615 defproxy.defsrv.maxconn = 0;
1616 defproxy.defsrv.slowstart = 0;
1617 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1618 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1619 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001620}
1621
Willy Tarreauade5ec42010-01-28 19:33:49 +01001622
Willy Tarreau63af98d2014-05-18 08:11:41 +02001623/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1624 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1625 * ERR_FATAL in case of error.
1626 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001627static int create_cond_regex_rule(const char *file, int line,
1628 struct proxy *px, int dir, int action, int flags,
1629 const char *cmd, const char *reg, const char *repl,
1630 const char **cond_start)
1631{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001632 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001633 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001634 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001635 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001636 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001637 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001638 int cs;
1639 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001640
1641 if (px == &defproxy) {
1642 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001643 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001644 goto err;
1645 }
1646
1647 if (*reg == 0) {
1648 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001649 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001650 goto err;
1651 }
1652
1653 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001654 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001655
Willy Tarreau5321c422010-01-28 20:35:13 +01001656 if (cond_start &&
1657 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001658 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1659 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1660 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001661 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001662 goto err;
1663 }
1664 }
1665 else if (cond_start && **cond_start) {
1666 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1667 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001668 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001669 goto err;
1670 }
1671
Willy Tarreau63af98d2014-05-18 08:11:41 +02001672 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001673 (dir == SMP_OPT_DIR_REQ) ?
1674 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1675 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1676 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001677
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001678 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001679 if (!preg) {
1680 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001681 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682 goto err;
1683 }
1684
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001685 cs = !(flags & REG_ICASE);
1686 cap = !(flags & REG_NOSUB);
1687 error = NULL;
1688 if (!regex_comp(reg, preg, cs, cap, &error)) {
1689 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1690 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001691 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001692 goto err;
1693 }
1694
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001695 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001696 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001697 if (repl && err) {
1698 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1699 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001700 ret_code |= ERR_ALERT | ERR_FATAL;
1701 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001702 }
1703
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001704 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001705 ret_code |= ERR_WARN;
1706
1707 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001708
Willy Tarreau63af98d2014-05-18 08:11:41 +02001709 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001710 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001711 err:
1712 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001713 free(errmsg);
1714 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001715}
1716
Willy Tarreaubaaee002006-06-26 02:48:02 +02001717/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001718 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001719 * Returns the error code, 0 if OK, or any combination of :
1720 * - ERR_ABORT: must abort ASAP
1721 * - ERR_FATAL: we can continue parsing but not start the service
1722 * - ERR_WARN: a warning has been emitted
1723 * - ERR_ALERT: an alert has been emitted
1724 * Only the two first ones can stop processing, the two others are just
1725 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001726 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001727int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1728{
1729 static struct peers *curpeers = NULL;
1730 struct peer *newpeer = NULL;
1731 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001732 struct bind_conf *bind_conf;
1733 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001734 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001735 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001736
1737 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001738 if (!*args[1]) {
1739 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001740 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001741 goto out;
1742 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001743
1744 err = invalid_char(args[1]);
1745 if (err) {
1746 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1747 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001748 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001749 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001750 }
1751
1752 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1753 /*
1754 * If there are two proxies with the same name only following
1755 * combinations are allowed:
1756 */
1757 if (strcmp(curpeers->id, args[1]) == 0) {
1758 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1759 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1760 err_code |= ERR_WARN;
1761 }
1762 }
1763
1764 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1765 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1766 err_code |= ERR_ALERT | ERR_ABORT;
1767 goto out;
1768 }
1769
1770 curpeers->next = peers;
1771 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001772 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001773 curpeers->conf.line = linenum;
1774 curpeers->last_change = now.tv_sec;
1775 curpeers->id = strdup(args[1]);
1776 }
1777 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001778 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001779 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001780 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001781
1782 if (!*args[2]) {
1783 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1784 file, linenum, args[0]);
1785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788
1789 err = invalid_char(args[1]);
1790 if (err) {
1791 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1792 file, linenum, *err, args[1]);
1793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1798 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1799 err_code |= ERR_ALERT | ERR_ABORT;
1800 goto out;
1801 }
1802
1803 /* the peers are linked backwards first */
1804 curpeers->count++;
1805 newpeer->next = curpeers->remote;
1806 curpeers->remote = newpeer;
1807 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001808 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001809 newpeer->conf.line = linenum;
1810
1811 newpeer->last_change = now.tv_sec;
1812 newpeer->id = strdup(args[1]);
1813
Willy Tarreau902636f2013-03-10 19:44:48 +01001814 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001815 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001816 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001819 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001820
1821 proto = protocol_by_family(sk->ss_family);
1822 if (!proto || !proto->connect) {
1823 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1824 file, linenum, args[0], args[1]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001828
1829 if (port1 != port2) {
1830 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1831 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001832 err_code |= ERR_ALERT | ERR_FATAL;
1833 goto out;
1834 }
1835
Willy Tarreau2aa38802013-02-20 19:20:59 +01001836 if (!port1) {
1837 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1838 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001839 err_code |= ERR_ALERT | ERR_FATAL;
1840 goto out;
1841 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001842
Emeric Brun32da3c42010-09-23 18:39:19 +02001843 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001844 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001845 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001846 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001847
Emeric Brun32da3c42010-09-23 18:39:19 +02001848 if (strcmp(newpeer->id, localpeer) == 0) {
1849 /* Current is local peer, it define a frontend */
1850 newpeer->local = 1;
1851
1852 if (!curpeers->peers_fe) {
1853 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1854 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1855 err_code |= ERR_ALERT | ERR_ABORT;
1856 goto out;
1857 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001858
Willy Tarreau237250c2011-07-29 01:49:03 +02001859 init_new_proxy(curpeers->peers_fe);
1860 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001861
1862 curpeers->peers_fe->last_change = now.tv_sec;
1863 curpeers->peers_fe->id = strdup(args[1]);
1864 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001865 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001866 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1867 curpeers->peers_fe->timeout.connect = 5000;
1868 curpeers->peers_fe->accept = peer_accept;
1869 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001870 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1871 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001872
1873 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1874
Willy Tarreau902636f2013-03-10 19:44:48 +01001875 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1876 if (errmsg && *errmsg) {
1877 indent_msg(&errmsg, 2);
1878 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001879 }
1880 else
1881 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1882 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001883 err_code |= ERR_FATAL;
1884 goto out;
1885 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001886
1887 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001888 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001889 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1890 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1891 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1892 l->accept = session_accept;
1893 l->handler = process_session;
1894 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1895 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1896 global.maxsock += l->maxconn;
1897 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001898 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001899 else {
1900 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1901 file, linenum, args[0], args[1],
1902 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1903 err_code |= ERR_FATAL;
1904 goto out;
1905 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001906 }
1907 } /* neither "peer" nor "peers" */
1908 else if (*args[0] != 0) {
1909 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1910 err_code |= ERR_ALERT | ERR_FATAL;
1911 goto out;
1912 }
1913
1914out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001915 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001916 return err_code;
1917}
1918
Willy Tarreau3842f002009-06-14 11:39:52 +02001919int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920{
1921 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001922 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001923 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001924 int rc;
1925 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001926 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001927 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001928 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001929 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001930 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001931
Willy Tarreau977b8e42006-12-29 14:19:17 +01001932 if (!strcmp(args[0], "listen"))
1933 rc = PR_CAP_LISTEN;
1934 else if (!strcmp(args[0], "frontend"))
1935 rc = PR_CAP_FE | PR_CAP_RS;
1936 else if (!strcmp(args[0], "backend"))
1937 rc = PR_CAP_BE | PR_CAP_RS;
1938 else if (!strcmp(args[0], "ruleset"))
1939 rc = PR_CAP_RS;
1940 else
1941 rc = PR_CAP_NONE;
1942
1943 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001944 struct ebpt_node *node;
1945
Willy Tarreaubaaee002006-06-26 02:48:02 +02001946 if (!*args[1]) {
1947 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1948 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1949 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001950 err_code |= ERR_ALERT | ERR_ABORT;
1951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001952 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001953
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001954 err = invalid_char(args[1]);
1955 if (err) {
1956 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1957 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001958 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001959 }
1960
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001961 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1962 curproxy = container_of(node, struct proxy, conf.by_name);
1963
1964 if (strcmp(curproxy->id, args[1]) != 0)
1965 break;
1966
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001967 /*
1968 * If there are two proxies with the same name only following
1969 * combinations are allowed:
1970 *
1971 * listen backend frontend ruleset
1972 * listen - - - -
1973 * backend - - OK -
1974 * frontend - OK - -
1975 * ruleset - - - -
1976 */
1977
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001978 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1979 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001980 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1981 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1982 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001983 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001984 }
1985 }
1986
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1988 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001989 err_code |= ERR_ALERT | ERR_ABORT;
1990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001992
Willy Tarreau97cb7802010-01-03 20:23:58 +01001993 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001994 curproxy->next = proxy;
1995 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001996 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1997 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001998 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001999 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002000 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002001 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002
2003 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002004 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002005 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002006
Willy Tarreau4348fad2012-09-20 16:48:07 +02002007 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2008
Willy Tarreau902636f2013-03-10 19:44:48 +01002009 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2010 if (errmsg && *errmsg) {
2011 indent_msg(&errmsg, 2);
2012 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002013 }
2014 else
2015 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2016 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002017 err_code |= ERR_FATAL;
2018 goto out;
2019 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002020
Willy Tarreau4348fad2012-09-20 16:48:07 +02002021 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002022 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 }
2025
2026 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002027 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002028 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002029
Willy Tarreaubaaee002006-06-26 02:48:02 +02002030 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002031 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002032 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002033 curproxy->no_options = defproxy.no_options;
2034 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002035 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002036 curproxy->except_net = defproxy.except_net;
2037 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002038 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002039 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002040
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002041 if (defproxy.fwdfor_hdr_len) {
2042 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2043 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2044 }
2045
Willy Tarreaub86db342009-11-30 11:50:16 +01002046 if (defproxy.orgto_hdr_len) {
2047 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2048 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2049 }
2050
Mark Lamourinec2247f02012-01-04 13:02:01 -05002051 if (defproxy.server_id_hdr_len) {
2052 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2053 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2054 }
2055
Willy Tarreau977b8e42006-12-29 14:19:17 +01002056 if (curproxy->cap & PR_CAP_FE) {
2057 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002058 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002059 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002060
2061 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002062 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2063 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002064
2065 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2066 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067
Willy Tarreau977b8e42006-12-29 14:19:17 +01002068 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002069 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002070 curproxy->fullconn = defproxy.fullconn;
2071 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002072 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002073
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002074 if (defproxy.check_req) {
2075 curproxy->check_req = calloc(1, defproxy.check_len);
2076 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2077 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002078 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002079
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002080 if (defproxy.expect_str) {
2081 curproxy->expect_str = strdup(defproxy.expect_str);
2082 if (defproxy.expect_regex) {
2083 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002084 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2085 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002086 }
2087 }
2088
Willy Tarreau67402132012-05-31 20:40:20 +02002089 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002090 if (defproxy.cookie_name)
2091 curproxy->cookie_name = strdup(defproxy.cookie_name);
2092 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002093 if (defproxy.cookie_domain)
2094 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002095
Willy Tarreau31936852010-10-06 16:59:56 +02002096 if (defproxy.cookie_maxidle)
2097 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2098
2099 if (defproxy.cookie_maxlife)
2100 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2101
Emeric Brun647caf12009-06-30 17:57:00 +02002102 if (defproxy.rdp_cookie_name)
2103 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2104 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2105
Willy Tarreau01732802007-11-01 22:48:15 +01002106 if (defproxy.url_param_name)
2107 curproxy->url_param_name = strdup(defproxy.url_param_name);
2108 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002109
Benoitaffb4812009-03-25 13:02:10 +01002110 if (defproxy.hh_name)
2111 curproxy->hh_name = strdup(defproxy.hh_name);
2112 curproxy->hh_len = defproxy.hh_len;
2113 curproxy->hh_match_domain = defproxy.hh_match_domain;
2114
Willy Tarreauef9a3602012-12-08 22:29:20 +01002115 if (defproxy.conn_src.iface_name)
2116 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2117 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002118 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002119#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002120 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002121#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002124 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002125 if (defproxy.capture_name)
2126 curproxy->capture_name = strdup(defproxy.capture_name);
2127 curproxy->capture_namelen = defproxy.capture_namelen;
2128 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002129 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002130
Willy Tarreau977b8e42006-12-29 14:19:17 +01002131 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002132 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002133 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002134 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002135 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002136 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002137 curproxy->mon_net = defproxy.mon_net;
2138 curproxy->mon_mask = defproxy.mon_mask;
2139 if (defproxy.monitor_uri)
2140 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2141 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002142 if (defproxy.defbe.name)
2143 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002144
2145 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002146 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2147 if (curproxy->conf.logformat_string &&
2148 curproxy->conf.logformat_string != default_http_log_format &&
2149 curproxy->conf.logformat_string != default_tcp_log_format &&
2150 curproxy->conf.logformat_string != clf_http_log_format)
2151 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2152
2153 if (defproxy.conf.lfs_file) {
2154 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2155 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2156 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002157 }
2158
2159 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002160 curproxy->timeout.connect = defproxy.timeout.connect;
2161 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002162 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002163 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002164 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002165 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002166 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002167 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002168 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002169 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002170 }
2171
Willy Tarreaubaaee002006-06-26 02:48:02 +02002172 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002173 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002174
2175 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002176 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002177 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002178 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002179 LIST_INIT(&node->list);
2180 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2181 }
2182
Willy Tarreau62a61232013-04-12 18:13:46 +02002183 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2184 if (curproxy->conf.uniqueid_format_string)
2185 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2186
Willy Tarreau094af4e2015-01-07 15:03:42 +01002187 if (defproxy.log_tag)
2188 curproxy->log_tag = strdup(defproxy.log_tag);
2189
Willy Tarreau62a61232013-04-12 18:13:46 +02002190 if (defproxy.conf.uif_file) {
2191 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2192 curproxy->conf.uif_line = defproxy.conf.uif_line;
2193 }
William Lallemanda73203e2012-03-12 12:48:57 +01002194
2195 /* copy default header unique id */
2196 if (defproxy.header_unique_id)
2197 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2198
William Lallemand82fe75c2012-10-23 10:25:10 +02002199 /* default compression options */
2200 if (defproxy.comp != NULL) {
2201 curproxy->comp = calloc(1, sizeof(struct comp));
2202 curproxy->comp->algos = defproxy.comp->algos;
2203 curproxy->comp->types = defproxy.comp->types;
2204 }
2205
Willy Tarreaubaaee002006-06-26 02:48:02 +02002206 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002207 curproxy->conf.used_listener_id = EB_ROOT;
2208 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002209
Simon Horman98637e52014-06-20 12:30:16 +09002210 if (defproxy.check_path)
2211 curproxy->check_path = strdup(defproxy.check_path);
2212 if (defproxy.check_command)
2213 curproxy->check_command = strdup(defproxy.check_command);
2214
Willy Tarreau93893792009-07-23 13:19:11 +02002215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002216 }
2217 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2218 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002219 /* FIXME-20070101: we should do this too at the end of the
2220 * config parsing to free all default values.
2221 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002222 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002223 free(defproxy.check_command);
2224 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002225 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002226 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002227 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002228 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002229 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002230 free(defproxy.capture_name);
2231 free(defproxy.monitor_uri);
2232 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002233 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002234 free(defproxy.fwdfor_hdr_name);
2235 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002236 free(defproxy.orgto_hdr_name);
2237 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002238 free(defproxy.server_id_hdr_name);
2239 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002240 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002241 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002242 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002243 free(defproxy.expect_regex);
2244 defproxy.expect_regex = NULL;
2245 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002246
Willy Tarreau62a61232013-04-12 18:13:46 +02002247 if (defproxy.conf.logformat_string != default_http_log_format &&
2248 defproxy.conf.logformat_string != default_tcp_log_format &&
2249 defproxy.conf.logformat_string != clf_http_log_format)
2250 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002251
Willy Tarreau62a61232013-04-12 18:13:46 +02002252 free(defproxy.conf.uniqueid_format_string);
2253 free(defproxy.conf.lfs_file);
2254 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002255 free(defproxy.log_tag);
Willy Tarreau196729e2012-05-31 19:30:26 +02002256
Willy Tarreaua534fea2008-08-03 12:19:50 +02002257 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002258 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002259
Willy Tarreaubaaee002006-06-26 02:48:02 +02002260 /* we cannot free uri_auth because it might already be used */
2261 init_default_instance();
2262 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002263 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2264 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002265 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002267 }
2268 else if (curproxy == NULL) {
2269 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
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 Tarreaua4312fa2013-04-02 16:34:32 +02002273
2274 /* update the current file and line being parsed */
2275 curproxy->conf.args.file = curproxy->conf.file;
2276 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277
2278 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002279 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2280 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2281 if (err_code & ERR_FATAL)
2282 goto out;
2283 }
2284 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002285 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002286 int cur_arg;
2287
Willy Tarreaubaaee002006-06-26 02:48:02 +02002288 if (curproxy == &defproxy) {
2289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002292 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002293 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002294 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002295
Willy Tarreau24709282013-03-10 21:32:12 +01002296 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002297 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002298 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002299 err_code |= ERR_ALERT | ERR_FATAL;
2300 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002301 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002302
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002303 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002304
2305 /* use default settings for unix sockets */
2306 bind_conf->ux.uid = global.unix_bind.ux.uid;
2307 bind_conf->ux.gid = global.unix_bind.ux.gid;
2308 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002309
2310 /* NOTE: the following line might create several listeners if there
2311 * are comma-separated IPs or port ranges. So all further processing
2312 * will have to be applied to all listeners created after last_listen.
2313 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002314 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2315 if (errmsg && *errmsg) {
2316 indent_msg(&errmsg, 2);
2317 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002318 }
2319 else
2320 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2321 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002322 err_code |= ERR_ALERT | ERR_FATAL;
2323 goto out;
2324 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002325
Willy Tarreau4348fad2012-09-20 16:48:07 +02002326 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2327 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002328 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002329 }
2330
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002331 cur_arg = 2;
2332 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002333 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002334 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002335 char *err;
2336
Willy Tarreau26982662012-09-12 23:17:10 +02002337 kw = bind_find_kw(args[cur_arg]);
2338 if (kw) {
2339 char *err = NULL;
2340 int code;
2341
2342 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002343 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2344 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002345 cur_arg += 1 + kw->skip ;
2346 err_code |= ERR_ALERT | ERR_FATAL;
2347 goto out;
2348 }
2349
Willy Tarreau4348fad2012-09-20 16:48:07 +02002350 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002351 err_code |= code;
2352
2353 if (code) {
2354 if (err && *err) {
2355 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002356 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002357 }
2358 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002359 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2360 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002361 if (code & ERR_FATAL) {
2362 free(err);
2363 cur_arg += 1 + kw->skip;
2364 goto out;
2365 }
2366 }
2367 free(err);
2368 cur_arg += 1 + kw->skip;
2369 continue;
2370 }
2371
Willy Tarreau8638f482012-09-18 18:01:17 +02002372 err = NULL;
2373 if (!bind_dumped) {
2374 bind_dump_kws(&err);
2375 indent_msg(&err, 4);
2376 bind_dumped = 1;
2377 }
2378
2379 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2380 file, linenum, args[0], args[1], args[cur_arg],
2381 err ? " Registered keywords :" : "", err ? err : "");
2382 free(err);
2383
Willy Tarreau93893792009-07-23 13:19:11 +02002384 err_code |= ERR_ALERT | ERR_FATAL;
2385 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002386 }
Willy Tarreau93893792009-07-23 13:19:11 +02002387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388 }
2389 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002390 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002391 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002393 err_code |= ERR_ALERT | ERR_FATAL;
2394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002395 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002396 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002397 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002398
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 /* flush useless bits */
2400 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002402 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002403 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002404 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002406
Willy Tarreau1c47f852006-07-09 08:22:27 +02002407 if (!*args[1]) {
2408 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2409 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002412 }
2413
Willy Tarreaua534fea2008-08-03 12:19:50 +02002414 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002415 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002416 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002417 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002418 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2419
Willy Tarreau93893792009-07-23 13:19:11 +02002420 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002421 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002422 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2423 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2424 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2425 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2426 else {
2427 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
2431 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002432 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002433 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002434
2435 if (curproxy == &defproxy) {
2436 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2437 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002440 }
2441
2442 if (!*args[1]) {
2443 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002445 err_code |= ERR_ALERT | ERR_FATAL;
2446 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002447 }
2448
2449 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002450 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002451
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002452 if (curproxy->uuid <= 0) {
2453 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002454 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002457 }
2458
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002459 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2460 if (node) {
2461 struct proxy *target = container_of(node, struct proxy, conf.id);
2462 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2463 file, linenum, proxy_type_str(curproxy), curproxy->id,
2464 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2465 err_code |= ERR_ALERT | ERR_FATAL;
2466 goto out;
2467 }
2468 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002469 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002470 else if (!strcmp(args[0], "description")) {
2471 int i, len=0;
2472 char *d;
2473
Cyril Bonté99ed3272010-01-24 23:29:44 +01002474 if (curproxy == &defproxy) {
2475 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2476 file, linenum, args[0]);
2477 err_code |= ERR_ALERT | ERR_FATAL;
2478 goto out;
2479 }
2480
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002481 if (!*args[1]) {
2482 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2483 file, linenum, args[0]);
2484 return -1;
2485 }
2486
Willy Tarreau348acfe2014-04-14 15:00:39 +02002487 for (i = 1; *args[i]; i++)
2488 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002489
2490 d = (char *)calloc(1, len);
2491 curproxy->desc = d;
2492
Willy Tarreau348acfe2014-04-14 15:00:39 +02002493 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2494 for (i = 2; *args[i]; i++)
2495 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002496
2497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002498 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2499 curproxy->state = PR_STSTOPPED;
2500 }
2501 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2502 curproxy->state = PR_STNEW;
2503 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002504 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2505 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002506 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002507
2508 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002509 unsigned int low, high;
2510
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002511 if (strcmp(args[cur_arg], "all") == 0) {
2512 set = 0;
2513 break;
2514 }
2515 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002516 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002517 }
2518 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002519 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002520 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002521 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002522 char *dash = strchr(args[cur_arg], '-');
2523
2524 low = high = str2uic(args[cur_arg]);
2525 if (dash)
2526 high = str2uic(dash + 1);
2527
2528 if (high < low) {
2529 unsigned int swap = low;
2530 low = high;
2531 high = swap;
2532 }
2533
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002534 if (low < 1 || high > LONGBITS) {
2535 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2536 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
2538 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002539 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002540 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002541 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002542 }
2543 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002544 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2545 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002546 err_code |= ERR_ALERT | ERR_FATAL;
2547 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002548 }
2549 cur_arg++;
2550 }
2551 curproxy->bind_proc = set;
2552 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002553 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002554 if (curproxy == &defproxy) {
2555 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
2557 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002558 }
2559
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002560 err = invalid_char(args[1]);
2561 if (err) {
2562 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2563 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002564 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002565 }
2566
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002567 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002568 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2569 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_ALERT | ERR_FATAL;
2571 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002572 }
2573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2575 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002579
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 if (*(args[1]) == 0) {
2581 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2582 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002583 err_code |= ERR_ALERT | ERR_FATAL;
2584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002586
Willy Tarreau67402132012-05-31 20:40:20 +02002587 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002588 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002589 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002590 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002591 curproxy->cookie_name = strdup(args[1]);
2592 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002593
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 cur_arg = 2;
2595 while (*(args[cur_arg])) {
2596 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002597 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
2599 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002600 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002601 }
2602 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002603 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002604 }
2605 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002606 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002607 }
2608 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002609 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002610 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002611 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002612 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002613 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002614 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002615 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002616 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002617 else if (!strcmp(args[cur_arg], "httponly")) {
2618 curproxy->ck_opts |= PR_CK_HTTPONLY;
2619 }
2620 else if (!strcmp(args[cur_arg], "secure")) {
2621 curproxy->ck_opts |= PR_CK_SECURE;
2622 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002623 else if (!strcmp(args[cur_arg], "domain")) {
2624 if (!*args[cur_arg + 1]) {
2625 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2626 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002627 err_code |= ERR_ALERT | ERR_FATAL;
2628 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002629 }
2630
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002631 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002632 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002633 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2634 " dots nor does not start with a dot."
2635 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002636 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002637 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002638 }
2639
2640 err = invalid_domainchar(args[cur_arg + 1]);
2641 if (err) {
2642 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2643 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002644 err_code |= ERR_ALERT | ERR_FATAL;
2645 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002646 }
2647
Willy Tarreau68a897b2009-12-03 23:28:34 +01002648 if (!curproxy->cookie_domain) {
2649 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2650 } else {
2651 /* one domain was already specified, add another one by
2652 * building the string which will be returned along with
2653 * the cookie.
2654 */
2655 char *new_ptr;
2656 int new_len = strlen(curproxy->cookie_domain) +
2657 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2658 new_ptr = malloc(new_len);
2659 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2660 free(curproxy->cookie_domain);
2661 curproxy->cookie_domain = new_ptr;
2662 }
Willy Tarreau31936852010-10-06 16:59:56 +02002663 cur_arg++;
2664 }
2665 else if (!strcmp(args[cur_arg], "maxidle")) {
2666 unsigned int maxidle;
2667 const char *res;
2668
2669 if (!*args[cur_arg + 1]) {
2670 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2671 file, linenum, args[cur_arg]);
2672 err_code |= ERR_ALERT | ERR_FATAL;
2673 goto out;
2674 }
2675
2676 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2677 if (res) {
2678 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2679 file, linenum, *res, args[cur_arg]);
2680 err_code |= ERR_ALERT | ERR_FATAL;
2681 goto out;
2682 }
2683 curproxy->cookie_maxidle = maxidle;
2684 cur_arg++;
2685 }
2686 else if (!strcmp(args[cur_arg], "maxlife")) {
2687 unsigned int maxlife;
2688 const char *res;
2689
2690 if (!*args[cur_arg + 1]) {
2691 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2692 file, linenum, args[cur_arg]);
2693 err_code |= ERR_ALERT | ERR_FATAL;
2694 goto out;
2695 }
2696
2697 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2698 if (res) {
2699 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2700 file, linenum, *res, args[cur_arg]);
2701 err_code |= ERR_ALERT | ERR_FATAL;
2702 goto out;
2703 }
2704 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002705 cur_arg++;
2706 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002708 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 +02002709 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002710 err_code |= ERR_ALERT | ERR_FATAL;
2711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002712 }
2713 cur_arg++;
2714 }
Willy Tarreau67402132012-05-31 20:40:20 +02002715 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002716 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2717 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002718 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002719 }
2720
Willy Tarreau67402132012-05-31 20:40:20 +02002721 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002722 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2723 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002724 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002725 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002726
Willy Tarreau67402132012-05-31 20:40:20 +02002727 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002728 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2729 file, linenum);
2730 err_code |= ERR_ALERT | ERR_FATAL;
2731 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman98637e52014-06-20 12:30:16 +09002733 else if (!strcmp(args[0], "external-check")) {
2734 if (*(args[1]) == 0) {
2735 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2736 file, linenum, args[0]);
2737 err_code |= ERR_ALERT | ERR_FATAL;
2738 goto out;
2739 }
2740
2741 if (!strcmp(args[1], "command")) {
2742 if (*(args[1]) == 0) {
2743 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2744 file, linenum, args[1]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748 free(curproxy->check_command);
2749 curproxy->check_command = strdup(args[2]);
2750 }
2751 else if (!strcmp(args[1], "path")) {
2752 if (*(args[1]) == 0) {
2753 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2754 file, linenum, args[1]);
2755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
2757 }
2758 free(curproxy->check_path);
2759 curproxy->check_path = strdup(args[2]);
2760 }
2761 else {
2762 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2763 file, linenum, args[1]);
2764 err_code |= ERR_ALERT | ERR_FATAL;
2765 goto out;
2766 }
2767 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002768 else if (!strcmp(args[0], "persist")) { /* persist */
2769 if (*(args[1]) == 0) {
2770 Alert("parsing [%s:%d] : missing persist method.\n",
2771 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_ALERT | ERR_FATAL;
2773 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002774 }
2775
2776 if (!strncmp(args[1], "rdp-cookie", 10)) {
2777 curproxy->options2 |= PR_O2_RDPC_PRST;
2778
Emeric Brunb982a3d2010-01-04 15:45:53 +01002779 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002780 const char *beg, *end;
2781
2782 beg = args[1] + 11;
2783 end = strchr(beg, ')');
2784
2785 if (!end || end == beg) {
2786 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2787 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002788 err_code |= ERR_ALERT | ERR_FATAL;
2789 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002790 }
2791
2792 free(curproxy->rdp_cookie_name);
2793 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2794 curproxy->rdp_cookie_len = end-beg;
2795 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002796 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002797 free(curproxy->rdp_cookie_name);
2798 curproxy->rdp_cookie_name = strdup("msts");
2799 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2800 }
2801 else { /* syntax */
2802 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2803 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002806 }
2807 }
2808 else {
2809 Alert("parsing [%s:%d] : unknown persist method.\n",
2810 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002811 err_code |= ERR_ALERT | ERR_FATAL;
2812 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002813 }
2814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002816 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002817
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002818 if (curproxy == &defproxy) {
2819 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
2822 }
2823
Willy Tarreau977b8e42006-12-29 14:19:17 +01002824 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002825 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002826
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002828 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 }
2833 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002834 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002835 curproxy->appsession_name = strdup(args[1]);
2836 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2837 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002838 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2839 if (err) {
2840 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2841 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002844 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002845 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002846
Willy Tarreau51041c72007-09-09 21:56:53 +02002847 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2848 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002849 err_code |= ERR_ALERT | ERR_ABORT;
2850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002852
2853 cur_arg = 6;
2854 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002855 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2856 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002857 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002858 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002859 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002860 } else if (!strcmp(args[cur_arg], "prefix")) {
2861 curproxy->options2 |= PR_O2_AS_PFX;
2862 } else if (!strcmp(args[cur_arg], "mode")) {
2863 if (!*args[cur_arg + 1]) {
2864 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2865 file, linenum, args[0], args[cur_arg]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869
2870 cur_arg++;
2871 if (!strcmp(args[cur_arg], "query-string")) {
2872 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2873 curproxy->options2 |= PR_O2_AS_M_QS;
2874 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2875 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2876 curproxy->options2 |= PR_O2_AS_M_PP;
2877 } else {
2878 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2879 err_code |= ERR_ALERT | ERR_FATAL;
2880 goto out;
2881 }
2882 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002883 cur_arg++;
2884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 } /* Url App Session */
2886 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002887 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002889
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002891 if (curproxy == &defproxy) {
2892 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2893 err_code |= ERR_ALERT | ERR_FATAL;
2894 goto out;
2895 }
2896
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 if (*(args[4]) == 0) {
2898 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2899 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002900 err_code |= ERR_ALERT | ERR_FATAL;
2901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002903 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002904 curproxy->capture_name = strdup(args[2]);
2905 curproxy->capture_namelen = strlen(curproxy->capture_name);
2906 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002907 curproxy->to_log |= LW_COOKIE;
2908 }
2909 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2910 struct cap_hdr *hdr;
2911
2912 if (curproxy == &defproxy) {
2913 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 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002916 }
2917
2918 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2919 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2920 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 }
2924
2925 hdr = calloc(sizeof(struct cap_hdr), 1);
2926 hdr->next = curproxy->req_cap;
2927 hdr->name = strdup(args[3]);
2928 hdr->namelen = strlen(args[3]);
2929 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002930 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002931 hdr->index = curproxy->nb_req_cap++;
2932 curproxy->req_cap = hdr;
2933 curproxy->to_log |= LW_REQHDR;
2934 }
2935 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2936 struct cap_hdr *hdr;
2937
2938 if (curproxy == &defproxy) {
2939 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 +02002940 err_code |= ERR_ALERT | ERR_FATAL;
2941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002942 }
2943
2944 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2945 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2946 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002947 err_code |= ERR_ALERT | ERR_FATAL;
2948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002949 }
2950 hdr = calloc(sizeof(struct cap_hdr), 1);
2951 hdr->next = curproxy->rsp_cap;
2952 hdr->name = strdup(args[3]);
2953 hdr->namelen = strlen(args[3]);
2954 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002955 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002956 hdr->index = curproxy->nb_rsp_cap++;
2957 curproxy->rsp_cap = hdr;
2958 curproxy->to_log |= LW_RSPHDR;
2959 }
2960 else {
2961 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2962 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002963 err_code |= ERR_ALERT | ERR_FATAL;
2964 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002965 }
2966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002968 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 if (*(args[1]) == 0) {
2972 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976 }
2977 curproxy->conn_retries = atol(args[1]);
2978 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002979 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002980 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002981
2982 if (curproxy == &defproxy) {
2983 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
2986 }
2987
Willy Tarreau20b0de52012-12-24 15:45:22 +01002988 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2989 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2990 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2991 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002992 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002993 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2994 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 +01002995 file, linenum, args[0]);
2996 err_code |= ERR_WARN;
2997 }
2998
Willy Tarreauff011f22011-01-06 17:51:27 +01002999 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003000
Willy Tarreauff011f22011-01-06 17:51:27 +01003001 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003002 err_code |= ERR_ALERT | ERR_ABORT;
3003 goto out;
3004 }
3005
Willy Tarreau5002f572014-04-23 01:32:02 +02003006 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003007 err_code |= warnif_cond_conflicts(rule->cond,
3008 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3009 file, linenum);
3010
Willy Tarreauff011f22011-01-06 17:51:27 +01003011 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003012 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003013 else if (!strcmp(args[0], "http-response")) { /* response access control */
3014 struct http_res_rule *rule;
3015
3016 if (curproxy == &defproxy) {
3017 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3018 err_code |= ERR_ALERT | ERR_FATAL;
3019 goto out;
3020 }
3021
3022 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3023 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3024 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3025 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3026 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3027 file, linenum, args[0]);
3028 err_code |= ERR_WARN;
3029 }
3030
3031 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3032
3033 if (!rule) {
3034 err_code |= ERR_ALERT | ERR_ABORT;
3035 goto out;
3036 }
3037
3038 err_code |= warnif_cond_conflicts(rule->cond,
3039 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3040 file, linenum);
3041
3042 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3043 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003044 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3045 /* set the header name and length into the proxy structure */
3046 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3047 err_code |= ERR_WARN;
3048
3049 if (!*args[1]) {
3050 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3051 file, linenum, args[0]);
3052 err_code |= ERR_ALERT | ERR_FATAL;
3053 goto out;
3054 }
3055
3056 /* set the desired header name */
3057 free(curproxy->server_id_hdr_name);
3058 curproxy->server_id_hdr_name = strdup(args[1]);
3059 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3060 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003061 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003062 struct http_req_rule *rule;
3063
Willy Tarreaub099aca2008-10-12 17:26:37 +02003064 if (curproxy == &defproxy) {
3065 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003068 }
3069
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003070 /* emulate "block" using "http-request block". Since these rules are supposed to
3071 * be processed before all http-request rules, we put them into their own list
3072 * and will insert them at the end.
3073 */
3074 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3075 if (!rule) {
3076 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003077 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003078 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003079 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3080 err_code |= warnif_cond_conflicts(rule->cond,
3081 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3082 file, linenum);
3083 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003084
3085 if (!already_warned(WARN_BLOCK_DEPRECATED))
3086 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]);
3087
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003088 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003089 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003090 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003091
Cyril Bonté99ed3272010-01-24 23:29:44 +01003092 if (curproxy == &defproxy) {
3093 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3094 err_code |= ERR_ALERT | ERR_FATAL;
3095 goto out;
3096 }
3097
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003098 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003099 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3100 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003103 }
3104
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003105 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003106 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003107 err_code |= warnif_cond_conflicts(rule->cond,
3108 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3109 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003110 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003111 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003112 struct switching_rule *rule;
3113
Willy Tarreaub099aca2008-10-12 17:26:37 +02003114 if (curproxy == &defproxy) {
3115 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003118 }
3119
Willy Tarreau55ea7572007-06-17 19:56:27 +02003120 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003121 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003122
3123 if (*(args[1]) == 0) {
3124 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003125 err_code |= ERR_ALERT | ERR_FATAL;
3126 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003127 }
3128
Willy Tarreauf51658d2014-04-23 01:21:56 +02003129 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3130 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3131 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3132 file, linenum, errmsg);
3133 err_code |= ERR_ALERT | ERR_FATAL;
3134 goto out;
3135 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003136
Willy Tarreauf51658d2014-04-23 01:21:56 +02003137 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003138 }
3139
3140 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3141 rule->cond = cond;
3142 rule->be.name = strdup(args[1]);
3143 LIST_INIT(&rule->list);
3144 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3145 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003146 else if (strcmp(args[0], "use-server") == 0) {
3147 struct server_rule *rule;
3148
3149 if (curproxy == &defproxy) {
3150 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3151 err_code |= ERR_ALERT | ERR_FATAL;
3152 goto out;
3153 }
3154
3155 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3156 err_code |= ERR_WARN;
3157
3158 if (*(args[1]) == 0) {
3159 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
3162 }
3163
3164 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3165 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3166 file, linenum, args[0]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003171 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3172 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3173 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003174 err_code |= ERR_ALERT | ERR_FATAL;
3175 goto out;
3176 }
3177
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003178 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003179
3180 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3181 rule->cond = cond;
3182 rule->srv.name = strdup(args[1]);
3183 LIST_INIT(&rule->list);
3184 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3185 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3186 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003187 else if ((!strcmp(args[0], "force-persist")) ||
3188 (!strcmp(args[0], "ignore-persist"))) {
3189 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003190
3191 if (curproxy == &defproxy) {
3192 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196
3197 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3198 err_code |= ERR_WARN;
3199
Willy Tarreauef6494c2010-01-28 17:12:36 +01003200 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003201 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3202 file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003207 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3208 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3209 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003210 err_code |= ERR_ALERT | ERR_FATAL;
3211 goto out;
3212 }
3213
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003214 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3215 * where force-persist is applied.
3216 */
3217 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003218
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003219 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003220 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003221 if (!strcmp(args[0], "force-persist")) {
3222 rule->type = PERSIST_TYPE_FORCE;
3223 } else {
3224 rule->type = PERSIST_TYPE_IGNORE;
3225 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003226 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003227 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003228 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003229 else if (!strcmp(args[0], "stick-table")) {
3230 int myidx = 1;
3231
Emeric Brun32da3c42010-09-23 18:39:19 +02003232 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 curproxy->table.type = (unsigned int)-1;
3234 while (*args[myidx]) {
3235 const char *err;
3236
3237 if (strcmp(args[myidx], "size") == 0) {
3238 myidx++;
3239 if (!*(args[myidx])) {
3240 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3241 file, linenum, args[myidx-1]);
3242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
3244 }
3245 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3246 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3247 file, linenum, *err, args[myidx-1]);
3248 err_code |= ERR_ALERT | ERR_FATAL;
3249 goto out;
3250 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003251 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003252 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003253 else if (strcmp(args[myidx], "peers") == 0) {
3254 myidx++;
Godbach50523162013-12-11 19:48:57 +08003255 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003256 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3257 file, linenum, args[myidx-1]);
3258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
Godbach50523162013-12-11 19:48:57 +08003260 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003261 curproxy->table.peers.name = strdup(args[myidx++]);
3262 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003263 else if (strcmp(args[myidx], "expire") == 0) {
3264 myidx++;
3265 if (!*(args[myidx])) {
3266 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3267 file, linenum, args[myidx-1]);
3268 err_code |= ERR_ALERT | ERR_FATAL;
3269 goto out;
3270 }
3271 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3272 if (err) {
3273 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3274 file, linenum, *err, args[myidx-1]);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
3277 }
3278 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003279 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003280 }
3281 else if (strcmp(args[myidx], "nopurge") == 0) {
3282 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003283 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003284 }
3285 else if (strcmp(args[myidx], "type") == 0) {
3286 myidx++;
3287 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3288 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3289 file, linenum, args[myidx]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
3292 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003293 /* myidx already points to next arg */
3294 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003295 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003296 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003297 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003298
3299 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003300 nw = args[myidx];
3301 while (*nw) {
3302 /* the "store" keyword supports a comma-separated list */
3303 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003304 sa = NULL; /* store arg */
3305 while (*nw && *nw != ',') {
3306 if (*nw == '(') {
3307 *nw = 0;
3308 sa = ++nw;
3309 while (*nw != ')') {
3310 if (!*nw) {
3311 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3312 file, linenum, args[0], cw);
3313 err_code |= ERR_ALERT | ERR_FATAL;
3314 goto out;
3315 }
3316 nw++;
3317 }
3318 *nw = '\0';
3319 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003320 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003321 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003322 if (*nw)
3323 *nw++ = '\0';
3324 type = stktable_get_data_type(cw);
3325 if (type < 0) {
3326 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3327 file, linenum, args[0], cw);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
Willy Tarreauac782882010-06-20 10:41:54 +02003331
3332 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3333 switch (err) {
3334 case PE_NONE: break;
3335 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003336 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3337 file, linenum, args[0], cw);
3338 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003339 break;
3340
3341 case PE_ARG_MISSING:
3342 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3343 file, linenum, args[0], cw);
3344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
3346
3347 case PE_ARG_NOT_USED:
3348 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3349 file, linenum, args[0], cw);
3350 err_code |= ERR_ALERT | ERR_FATAL;
3351 goto out;
3352
3353 default:
3354 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3355 file, linenum, args[0], cw);
3356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003358 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003359 }
3360 myidx++;
3361 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003362 else {
3363 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3364 file, linenum, args[myidx]);
3365 err_code |= ERR_ALERT | ERR_FATAL;
3366 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003367 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003368 }
3369
3370 if (!curproxy->table.size) {
3371 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3372 file, linenum);
3373 err_code |= ERR_ALERT | ERR_FATAL;
3374 goto out;
3375 }
3376
3377 if (curproxy->table.type == (unsigned int)-1) {
3378 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3379 file, linenum);
3380 err_code |= ERR_ALERT | ERR_FATAL;
3381 goto out;
3382 }
3383 }
3384 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003385 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003386 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003387 int myidx = 0;
3388 const char *name = NULL;
3389 int flags;
3390
3391 if (curproxy == &defproxy) {
3392 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3393 err_code |= ERR_ALERT | ERR_FATAL;
3394 goto out;
3395 }
3396
3397 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3398 err_code |= ERR_WARN;
3399 goto out;
3400 }
3401
3402 myidx++;
3403 if ((strcmp(args[myidx], "store") == 0) ||
3404 (strcmp(args[myidx], "store-request") == 0)) {
3405 myidx++;
3406 flags = STK_IS_STORE;
3407 }
3408 else if (strcmp(args[myidx], "store-response") == 0) {
3409 myidx++;
3410 flags = STK_IS_STORE | STK_ON_RSP;
3411 }
3412 else if (strcmp(args[myidx], "match") == 0) {
3413 myidx++;
3414 flags = STK_IS_MATCH;
3415 }
3416 else if (strcmp(args[myidx], "on") == 0) {
3417 myidx++;
3418 flags = STK_IS_MATCH | STK_IS_STORE;
3419 }
3420 else {
3421 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3422 err_code |= ERR_ALERT | ERR_FATAL;
3423 goto out;
3424 }
3425
3426 if (*(args[myidx]) == 0) {
3427 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
3430 }
3431
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003432 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003433 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003434 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003435 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003436 err_code |= ERR_ALERT | ERR_FATAL;
3437 goto out;
3438 }
3439
3440 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003441 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3442 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3443 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003444 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003445 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003446 goto out;
3447 }
3448 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003449 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3450 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3451 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003452 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003453 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003454 goto out;
3455 }
3456 }
3457
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003458 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003459 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003460
Emeric Brunb982a3d2010-01-04 15:45:53 +01003461 if (strcmp(args[myidx], "table") == 0) {
3462 myidx++;
3463 name = args[myidx++];
3464 }
3465
Willy Tarreauef6494c2010-01-28 17:12:36 +01003466 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003467 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3468 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3469 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003470 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003471 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003472 goto out;
3473 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003474 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003475 else if (*(args[myidx])) {
3476 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3477 file, linenum, args[0], args[myidx]);
3478 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003479 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003480 goto out;
3481 }
Emeric Brun97679e72010-09-23 17:56:44 +02003482 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003483 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003484 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003485 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003486
Emeric Brunb982a3d2010-01-04 15:45:53 +01003487 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3488 rule->cond = cond;
3489 rule->expr = expr;
3490 rule->flags = flags;
3491 rule->table.name = name ? strdup(name) : NULL;
3492 LIST_INIT(&rule->list);
3493 if (flags & STK_ON_RSP)
3494 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3495 else
3496 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3497 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 else if (!strcmp(args[0], "stats")) {
3499 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3500 curproxy->uri_auth = NULL; /* we must detach from the default config */
3501
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003502 if (!*args[1]) {
3503 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003504 } else if (!strcmp(args[1], "admin")) {
3505 struct stats_admin_rule *rule;
3506
3507 if (curproxy == &defproxy) {
3508 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3509 err_code |= ERR_ALERT | ERR_FATAL;
3510 goto out;
3511 }
3512
3513 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3514 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3515 err_code |= ERR_ALERT | ERR_ABORT;
3516 goto out;
3517 }
3518
3519 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3520 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3521 file, linenum, args[0], args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003525 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3526 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3527 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003532 err_code |= warnif_cond_conflicts(cond,
3533 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3534 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003535
3536 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3537 rule->cond = cond;
3538 LIST_INIT(&rule->list);
3539 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003540 } else if (!strcmp(args[1], "uri")) {
3541 if (*(args[2]) == 0) {
3542 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3546 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_ALERT | ERR_ABORT;
3548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 }
3550 } else if (!strcmp(args[1], "realm")) {
3551 if (*(args[2]) == 0) {
3552 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003553 err_code |= ERR_ALERT | ERR_FATAL;
3554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003555 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3556 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003557 err_code |= ERR_ALERT | ERR_ABORT;
3558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003560 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003561 unsigned interval;
3562
3563 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3564 if (err) {
3565 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3566 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003569 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3570 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003571 err_code |= ERR_ALERT | ERR_ABORT;
3572 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003573 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003574 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003575 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003576
3577 if (curproxy == &defproxy) {
3578 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
3581 }
3582
3583 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3584 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3585 err_code |= ERR_ALERT | ERR_ABORT;
3586 goto out;
3587 }
3588
Willy Tarreauff011f22011-01-06 17:51:27 +01003589 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3590 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003591 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3592 file, linenum, args[0]);
3593 err_code |= ERR_WARN;
3594 }
3595
Willy Tarreauff011f22011-01-06 17:51:27 +01003596 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003597
Willy Tarreauff011f22011-01-06 17:51:27 +01003598 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003599 err_code |= ERR_ALERT | ERR_ABORT;
3600 goto out;
3601 }
3602
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003603 err_code |= warnif_cond_conflicts(rule->cond,
3604 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3605 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003606 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003607
Willy Tarreaubaaee002006-06-26 02:48:02 +02003608 } else if (!strcmp(args[1], "auth")) {
3609 if (*(args[2]) == 0) {
3610 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003613 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3614 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_ABORT;
3616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
3618 } else if (!strcmp(args[1], "scope")) {
3619 if (*(args[2]) == 0) {
3620 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003621 err_code |= ERR_ALERT | ERR_FATAL;
3622 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003623 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3624 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003625 err_code |= ERR_ALERT | ERR_ABORT;
3626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 }
3628 } else if (!strcmp(args[1], "enable")) {
3629 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3630 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_ABORT;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003634 } else if (!strcmp(args[1], "hide-version")) {
3635 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3636 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_ALERT | ERR_ABORT;
3638 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003639 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003640 } else if (!strcmp(args[1], "show-legends")) {
3641 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3642 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3643 err_code |= ERR_ALERT | ERR_ABORT;
3644 goto out;
3645 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003646 } else if (!strcmp(args[1], "show-node")) {
3647
3648 if (*args[2]) {
3649 int i;
3650 char c;
3651
3652 for (i=0; args[2][i]; i++) {
3653 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003654 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3655 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003656 break;
3657 }
3658
3659 if (!i || args[2][i]) {
3660 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3661 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3662 file, linenum, args[0], args[1]);
3663 err_code |= ERR_ALERT | ERR_FATAL;
3664 goto out;
3665 }
3666 }
3667
3668 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3669 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3670 err_code |= ERR_ALERT | ERR_ABORT;
3671 goto out;
3672 }
3673 } else if (!strcmp(args[1], "show-desc")) {
3674 char *desc = NULL;
3675
3676 if (*args[2]) {
3677 int i, len=0;
3678 char *d;
3679
Willy Tarreau348acfe2014-04-14 15:00:39 +02003680 for (i = 2; *args[i]; i++)
3681 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003682
3683 desc = d = (char *)calloc(1, len);
3684
Willy Tarreau348acfe2014-04-14 15:00:39 +02003685 d += snprintf(d, desc + len - d, "%s", args[2]);
3686 for (i = 3; *args[i]; i++)
3687 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003688 }
3689
3690 if (!*args[2] && !global.desc)
3691 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3692 file, linenum, args[1]);
3693 else {
3694 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3695 free(desc);
3696 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3697 err_code |= ERR_ALERT | ERR_ABORT;
3698 goto out;
3699 }
3700 free(desc);
3701 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003703stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003704 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 +01003705 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003706 err_code |= ERR_ALERT | ERR_FATAL;
3707 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 }
3709 }
3710 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003711 int optnum;
3712
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003713 if (*(args[1]) == '\0') {
3714 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3715 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003716 err_code |= ERR_ALERT | ERR_FATAL;
3717 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003718 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003719
3720 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3721 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003722 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3723 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3724 file, linenum, cfg_opts[optnum].name);
3725 err_code |= ERR_ALERT | ERR_FATAL;
3726 goto out;
3727 }
Willy Tarreau93893792009-07-23 13:19:11 +02003728 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3729 err_code |= ERR_WARN;
3730 goto out;
3731 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003732
Willy Tarreau3842f002009-06-14 11:39:52 +02003733 curproxy->no_options &= ~cfg_opts[optnum].val;
3734 curproxy->options &= ~cfg_opts[optnum].val;
3735
3736 switch (kwm) {
3737 case KWM_STD:
3738 curproxy->options |= cfg_opts[optnum].val;
3739 break;
3740 case KWM_NO:
3741 curproxy->no_options |= cfg_opts[optnum].val;
3742 break;
3743 case KWM_DEF: /* already cleared */
3744 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003745 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003746
Willy Tarreau93893792009-07-23 13:19:11 +02003747 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003748 }
3749 }
3750
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003751 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3752 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003753 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3754 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3755 file, linenum, cfg_opts2[optnum].name);
3756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
3758 }
Willy Tarreau93893792009-07-23 13:19:11 +02003759 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3760 err_code |= ERR_WARN;
3761 goto out;
3762 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003763
Willy Tarreau3842f002009-06-14 11:39:52 +02003764 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3765 curproxy->options2 &= ~cfg_opts2[optnum].val;
3766
3767 switch (kwm) {
3768 case KWM_STD:
3769 curproxy->options2 |= cfg_opts2[optnum].val;
3770 break;
3771 case KWM_NO:
3772 curproxy->no_options2 |= cfg_opts2[optnum].val;
3773 break;
3774 case KWM_DEF: /* already cleared */
3775 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003776 }
Willy Tarreau93893792009-07-23 13:19:11 +02003777 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003778 }
3779 }
3780
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003781 /* HTTP options override each other. They can be cancelled using
3782 * "no option xxx" which only switches to default mode if the mode
3783 * was this one (useful for cancelling options set in defaults
3784 * sections).
3785 */
3786 if (strcmp(args[1], "httpclose") == 0) {
3787 if (kwm == KWM_STD) {
3788 curproxy->options &= ~PR_O_HTTP_MODE;
3789 curproxy->options |= PR_O_HTTP_PCL;
3790 goto out;
3791 }
3792 else if (kwm == KWM_NO) {
3793 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3794 curproxy->options &= ~PR_O_HTTP_MODE;
3795 goto out;
3796 }
3797 }
3798 else if (strcmp(args[1], "forceclose") == 0) {
3799 if (kwm == KWM_STD) {
3800 curproxy->options &= ~PR_O_HTTP_MODE;
3801 curproxy->options |= PR_O_HTTP_FCL;
3802 goto out;
3803 }
3804 else if (kwm == KWM_NO) {
3805 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3806 curproxy->options &= ~PR_O_HTTP_MODE;
3807 goto out;
3808 }
3809 }
3810 else if (strcmp(args[1], "http-server-close") == 0) {
3811 if (kwm == KWM_STD) {
3812 curproxy->options &= ~PR_O_HTTP_MODE;
3813 curproxy->options |= PR_O_HTTP_SCL;
3814 goto out;
3815 }
3816 else if (kwm == KWM_NO) {
3817 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3818 curproxy->options &= ~PR_O_HTTP_MODE;
3819 goto out;
3820 }
3821 }
3822 else if (strcmp(args[1], "http-keep-alive") == 0) {
3823 if (kwm == KWM_STD) {
3824 curproxy->options &= ~PR_O_HTTP_MODE;
3825 curproxy->options |= PR_O_HTTP_KAL;
3826 goto out;
3827 }
3828 else if (kwm == KWM_NO) {
3829 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3830 curproxy->options &= ~PR_O_HTTP_MODE;
3831 goto out;
3832 }
3833 }
3834 else if (strcmp(args[1], "http-tunnel") == 0) {
3835 if (kwm == KWM_STD) {
3836 curproxy->options &= ~PR_O_HTTP_MODE;
3837 curproxy->options |= PR_O_HTTP_TUN;
3838 goto out;
3839 }
3840 else if (kwm == KWM_NO) {
3841 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3842 curproxy->options &= ~PR_O_HTTP_MODE;
3843 goto out;
3844 }
3845 }
3846
Willy Tarreau3842f002009-06-14 11:39:52 +02003847 if (kwm != KWM_STD) {
3848 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003849 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003852 }
3853
Emeric Brun3a058f32009-06-30 18:26:00 +02003854 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003855 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003857 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003858 if (*(args[2]) != '\0') {
3859 if (!strcmp(args[2], "clf")) {
3860 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003861 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003862 } else {
3863 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003866 }
3867 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003868 if (curproxy->conf.logformat_string != default_http_log_format &&
3869 curproxy->conf.logformat_string != default_tcp_log_format &&
3870 curproxy->conf.logformat_string != clf_http_log_format)
3871 free(curproxy->conf.logformat_string);
3872 curproxy->conf.logformat_string = logformat;
3873
3874 free(curproxy->conf.lfs_file);
3875 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3876 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003877 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003878 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003879 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003880 if (curproxy->conf.logformat_string != default_http_log_format &&
3881 curproxy->conf.logformat_string != default_tcp_log_format &&
3882 curproxy->conf.logformat_string != clf_http_log_format)
3883 free(curproxy->conf.logformat_string);
3884 curproxy->conf.logformat_string = default_tcp_log_format;
3885
3886 free(curproxy->conf.lfs_file);
3887 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3888 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003890 else if (!strcmp(args[1], "tcpka")) {
3891 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003892 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003893 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003894
3895 if (curproxy->cap & PR_CAP_FE)
3896 curproxy->options |= PR_O_TCP_CLI_KA;
3897 if (curproxy->cap & PR_CAP_BE)
3898 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003899 }
3900 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003901 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003902 err_code |= ERR_WARN;
3903
Willy Tarreaubaaee002006-06-26 02:48:02 +02003904 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003905 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003906 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003907 curproxy->options2 &= ~PR_O2_CHK_ANY;
3908 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003909 if (!*args[2]) { /* no argument */
3910 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3911 curproxy->check_len = strlen(DEF_CHECK_REQ);
3912 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003913 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003914 curproxy->check_req = (char *)malloc(reqlen);
3915 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003916 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003917 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003918 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003919 if (*args[4])
3920 reqlen += strlen(args[4]);
3921 else
3922 reqlen += strlen("HTTP/1.0");
3923
3924 curproxy->check_req = (char *)malloc(reqlen);
3925 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003926 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003927 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003928 }
3929 else if (!strcmp(args[1], "ssl-hello-chk")) {
3930 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003931 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003932 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003933
Willy Tarreaua534fea2008-08-03 12:19:50 +02003934 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003935 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003936 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003937 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003938 }
Willy Tarreau23677902007-05-08 23:50:35 +02003939 else if (!strcmp(args[1], "smtpchk")) {
3940 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003941 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003942 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003943 curproxy->options2 &= ~PR_O2_CHK_ANY;
3944 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003945
3946 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3947 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3948 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3949 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3950 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3951 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3952 curproxy->check_req = (char *)malloc(reqlen);
3953 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3954 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3955 } else {
3956 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3957 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3958 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3959 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3960 }
3961 }
3962 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003963 else if (!strcmp(args[1], "pgsql-check")) {
3964 /* use PostgreSQL request to check servers' health */
3965 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3966 err_code |= ERR_WARN;
3967
3968 free(curproxy->check_req);
3969 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003970 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003971 curproxy->options2 |= PR_O2_PGSQL_CHK;
3972
3973 if (*(args[2])) {
3974 int cur_arg = 2;
3975
3976 while (*(args[cur_arg])) {
3977 if (strcmp(args[cur_arg], "user") == 0) {
3978 char * packet;
3979 uint32_t packet_len;
3980 uint32_t pv;
3981
3982 /* suboption header - needs additional argument for it */
3983 if (*(args[cur_arg+1]) == 0) {
3984 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3985 file, linenum, args[0], args[1], args[cur_arg]);
3986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
3988 }
3989
3990 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3991 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3992 pv = htonl(0x30000); /* protocol version 3.0 */
3993
3994 packet = (char*) calloc(1, packet_len);
3995
3996 memcpy(packet + 4, &pv, 4);
3997
3998 /* copy "user" */
3999 memcpy(packet + 8, "user", 4);
4000
4001 /* copy username */
4002 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4003
4004 free(curproxy->check_req);
4005 curproxy->check_req = packet;
4006 curproxy->check_len = packet_len;
4007
4008 packet_len = htonl(packet_len);
4009 memcpy(packet, &packet_len, 4);
4010 cur_arg += 2;
4011 } else {
4012 /* unknown suboption - catchall */
4013 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4014 file, linenum, args[0], args[1]);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 } /* end while loop */
4019 }
4020 }
4021
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004022 else if (!strcmp(args[1], "redis-check")) {
4023 /* use REDIS PING request to check servers' health */
4024 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4025 err_code |= ERR_WARN;
4026
4027 free(curproxy->check_req);
4028 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004029 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004030 curproxy->options2 |= PR_O2_REDIS_CHK;
4031
4032 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4033 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4034 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4035 }
4036
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004037 else if (!strcmp(args[1], "mysql-check")) {
4038 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004039 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4040 err_code |= ERR_WARN;
4041
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004042 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004043 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004044 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004045 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004046
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004047 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004048 * const char mysql40_client_auth_pkt[] = {
4049 * "\x0e\x00\x00" // packet length
4050 * "\x01" // packet number
4051 * "\x00\x00" // client capabilities
4052 * "\x00\x00\x01" // max packet
4053 * "haproxy\x00" // username (null terminated string)
4054 * "\x00" // filler (always 0x00)
4055 * "\x01\x00\x00" // packet length
4056 * "\x00" // packet number
4057 * "\x01" // COM_QUIT command
4058 * };
4059 */
4060
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004061 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4062 * const char mysql41_client_auth_pkt[] = {
4063 * "\x0e\x00\x00\" // packet length
4064 * "\x01" // packet number
4065 * "\x00\x00\x00\x00" // client capabilities
4066 * "\x00\x00\x00\x01" // max packet
4067 * "\x21" // character set (UTF-8)
4068 * char[23] // All zeroes
4069 * "haproxy\x00" // username (null terminated string)
4070 * "\x00" // filler (always 0x00)
4071 * "\x01\x00\x00" // packet length
4072 * "\x00" // packet number
4073 * "\x01" // COM_QUIT command
4074 * };
4075 */
4076
4077
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004078 if (*(args[2])) {
4079 int cur_arg = 2;
4080
4081 while (*(args[cur_arg])) {
4082 if (strcmp(args[cur_arg], "user") == 0) {
4083 char *mysqluser;
4084 int packetlen, reqlen, userlen;
4085
4086 /* suboption header - needs additional argument for it */
4087 if (*(args[cur_arg+1]) == 0) {
4088 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4089 file, linenum, args[0], args[1], args[cur_arg]);
4090 err_code |= ERR_ALERT | ERR_FATAL;
4091 goto out;
4092 }
4093 mysqluser = args[cur_arg + 1];
4094 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004095
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004096 if (*(args[cur_arg+2])) {
4097 if (!strcmp(args[cur_arg+2], "post-41")) {
4098 packetlen = userlen + 7 + 27;
4099 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004100
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004101 free(curproxy->check_req);
4102 curproxy->check_req = (char *)calloc(1, reqlen);
4103 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004104
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004105 snprintf(curproxy->check_req, 4, "%c%c%c",
4106 ((unsigned char) packetlen & 0xff),
4107 ((unsigned char) (packetlen >> 8) & 0xff),
4108 ((unsigned char) (packetlen >> 16) & 0xff));
4109
4110 curproxy->check_req[3] = 1;
4111 curproxy->check_req[5] = 130;
4112 curproxy->check_req[11] = 1;
4113 curproxy->check_req[12] = 33;
4114 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4115 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4116 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4117 cur_arg += 3;
4118 } else {
4119 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122 }
4123 } else {
4124 packetlen = userlen + 7;
4125 reqlen = packetlen + 9;
4126
4127 free(curproxy->check_req);
4128 curproxy->check_req = (char *)calloc(1, reqlen);
4129 curproxy->check_len = reqlen;
4130
4131 snprintf(curproxy->check_req, 4, "%c%c%c",
4132 ((unsigned char) packetlen & 0xff),
4133 ((unsigned char) (packetlen >> 8) & 0xff),
4134 ((unsigned char) (packetlen >> 16) & 0xff));
4135
4136 curproxy->check_req[3] = 1;
4137 curproxy->check_req[5] = 128;
4138 curproxy->check_req[8] = 1;
4139 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4140 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4141 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4142 cur_arg += 2;
4143 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004144 } else {
4145 /* unknown suboption - catchall */
4146 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4147 file, linenum, args[0], args[1]);
4148 err_code |= ERR_ALERT | ERR_FATAL;
4149 goto out;
4150 }
4151 } /* end while loop */
4152 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004153 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004154 else if (!strcmp(args[1], "ldap-check")) {
4155 /* use LDAP request to check servers' health */
4156 free(curproxy->check_req);
4157 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004158 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004159 curproxy->options2 |= PR_O2_LDAP_CHK;
4160
4161 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4162 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4163 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4164 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004165 else if (!strcmp(args[1], "tcp-check")) {
4166 /* use raw TCPCHK send/expect to check servers' health */
4167 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4168 err_code |= ERR_WARN;
4169
4170 free(curproxy->check_req);
4171 curproxy->check_req = NULL;
4172 curproxy->options2 &= ~PR_O2_CHK_ANY;
4173 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4174 }
Simon Horman98637e52014-06-20 12:30:16 +09004175 else if (!strcmp(args[1], "external-check")) {
4176 /* excute an external command to check servers' health */
4177 free(curproxy->check_req);
4178 curproxy->check_req = NULL;
4179 curproxy->options2 &= ~PR_O2_CHK_ANY;
4180 curproxy->options2 |= PR_O2_EXT_CHK;
4181 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004182 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004183 int cur_arg;
4184
4185 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4186 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004187 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004188
Willy Tarreau87cf5142011-08-19 22:57:24 +02004189 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004190
4191 free(curproxy->fwdfor_hdr_name);
4192 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4193 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4194
4195 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4196 cur_arg = 2;
4197 while (*(args[cur_arg])) {
4198 if (!strcmp(args[cur_arg], "except")) {
4199 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004200 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004201 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4202 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_FATAL;
4204 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004205 }
4206 /* flush useless bits */
4207 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004208 cur_arg += 2;
4209 } else if (!strcmp(args[cur_arg], "header")) {
4210 /* suboption header - needs additional argument for it */
4211 if (*(args[cur_arg+1]) == 0) {
4212 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4213 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004216 }
4217 free(curproxy->fwdfor_hdr_name);
4218 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4219 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4220 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004221 } else if (!strcmp(args[cur_arg], "if-none")) {
4222 curproxy->options &= ~PR_O_FF_ALWAYS;
4223 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004224 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004225 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004226 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004227 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004228 err_code |= ERR_ALERT | ERR_FATAL;
4229 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004230 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004231 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004232 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004233 else if (!strcmp(args[1], "originalto")) {
4234 int cur_arg;
4235
4236 /* insert x-original-to field, but not for the IP address listed as an except.
4237 * set default options (ie: bitfield, header name, etc)
4238 */
4239
4240 curproxy->options |= PR_O_ORGTO;
4241
4242 free(curproxy->orgto_hdr_name);
4243 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4244 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4245
Willy Tarreau87cf5142011-08-19 22:57:24 +02004246 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004247 cur_arg = 2;
4248 while (*(args[cur_arg])) {
4249 if (!strcmp(args[cur_arg], "except")) {
4250 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004251 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 +02004252 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4253 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004254 err_code |= ERR_ALERT | ERR_FATAL;
4255 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004256 }
4257 /* flush useless bits */
4258 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4259 cur_arg += 2;
4260 } else if (!strcmp(args[cur_arg], "header")) {
4261 /* suboption header - needs additional argument for it */
4262 if (*(args[cur_arg+1]) == 0) {
4263 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4264 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004265 err_code |= ERR_ALERT | ERR_FATAL;
4266 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004267 }
4268 free(curproxy->orgto_hdr_name);
4269 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4270 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4271 cur_arg += 2;
4272 } else {
4273 /* unknown suboption - catchall */
4274 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4275 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004276 err_code |= ERR_ALERT | ERR_FATAL;
4277 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004278 }
4279 } /* end while loop */
4280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004281 else {
4282 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004283 err_code |= ERR_ALERT | ERR_FATAL;
4284 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004285 }
Willy Tarreau93893792009-07-23 13:19:11 +02004286 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004287 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004288 else if (!strcmp(args[0], "default_backend")) {
4289 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004290 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004291
4292 if (*(args[1]) == 0) {
4293 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004294 err_code |= ERR_ALERT | ERR_FATAL;
4295 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004296 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004297 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004298 curproxy->defbe.name = strdup(args[1]);
4299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004300 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004301 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004302 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004303
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004304 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4305 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 +01004306 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004307 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004308 /* enable reconnections to dispatch */
4309 curproxy->options |= PR_O_REDISP;
4310 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004311 else if (!strcmp(args[0], "http-check")) {
4312 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004313 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004314
4315 if (strcmp(args[1], "disable-on-404") == 0) {
4316 /* enable a graceful server shutdown on an HTTP 404 response */
4317 curproxy->options |= PR_O_DISABLE404;
4318 }
Willy Tarreauef781042010-01-27 11:53:01 +01004319 else if (strcmp(args[1], "send-state") == 0) {
4320 /* enable emission of the apparent state of a server in HTTP checks */
4321 curproxy->options2 |= PR_O2_CHK_SNDST;
4322 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004323 else if (strcmp(args[1], "expect") == 0) {
4324 const char *ptr_arg;
4325 int cur_arg;
4326
4327 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4328 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
4331 }
4332
4333 cur_arg = 2;
4334 /* consider exclamation marks, sole or at the beginning of a word */
4335 while (*(ptr_arg = args[cur_arg])) {
4336 while (*ptr_arg == '!') {
4337 curproxy->options2 ^= PR_O2_EXP_INV;
4338 ptr_arg++;
4339 }
4340 if (*ptr_arg)
4341 break;
4342 cur_arg++;
4343 }
4344 /* now ptr_arg points to the beginning of a word past any possible
4345 * exclamation mark, and cur_arg is the argument which holds this word.
4346 */
4347 if (strcmp(ptr_arg, "status") == 0) {
4348 if (!*(args[cur_arg + 1])) {
4349 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4350 file, linenum, args[0], args[1], ptr_arg);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004355 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004356 curproxy->expect_str = strdup(args[cur_arg + 1]);
4357 }
4358 else if (strcmp(ptr_arg, "string") == 0) {
4359 if (!*(args[cur_arg + 1])) {
4360 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4361 file, linenum, args[0], args[1], ptr_arg);
4362 err_code |= ERR_ALERT | ERR_FATAL;
4363 goto out;
4364 }
4365 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004366 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004367 curproxy->expect_str = strdup(args[cur_arg + 1]);
4368 }
4369 else if (strcmp(ptr_arg, "rstatus") == 0) {
4370 if (!*(args[cur_arg + 1])) {
4371 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4372 file, linenum, args[0], args[1], ptr_arg);
4373 err_code |= ERR_ALERT | ERR_FATAL;
4374 goto out;
4375 }
4376 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004377 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004378 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004379 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004380 free(curproxy->expect_regex);
4381 curproxy->expect_regex = NULL;
4382 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004383 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004384 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4385 error = NULL;
4386 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4387 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4388 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4389 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
4392 }
4393 }
4394 else if (strcmp(ptr_arg, "rstring") == 0) {
4395 if (!*(args[cur_arg + 1])) {
4396 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4397 file, linenum, args[0], args[1], ptr_arg);
4398 err_code |= ERR_ALERT | ERR_FATAL;
4399 goto out;
4400 }
4401 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004402 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004403 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004404 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004405 free(curproxy->expect_regex);
4406 curproxy->expect_regex = NULL;
4407 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004408 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004409 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4410 error = NULL;
4411 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4412 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4413 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4414 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418 }
4419 else {
4420 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4421 file, linenum, args[0], args[1], ptr_arg);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 }
4425 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004426 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004427 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 +02004428 err_code |= ERR_ALERT | ERR_FATAL;
4429 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004430 }
4431 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004432 else if (!strcmp(args[0], "tcp-check")) {
4433 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4434 err_code |= ERR_WARN;
4435
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004436 if (strcmp(args[1], "connect") == 0) {
4437 const char *ptr_arg;
4438 int cur_arg;
4439 struct tcpcheck_rule *tcpcheck;
4440 struct list *l;
4441
4442 /* check if first rule is also a 'connect' action */
4443 l = (struct list *)&curproxy->tcpcheck_rules;
4444 if (l->p != l->n) {
4445 tcpcheck = (struct tcpcheck_rule *)l->n;
4446 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4447 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4448 file, linenum);
4449 err_code |= ERR_ALERT | ERR_FATAL;
4450 goto out;
4451 }
4452 }
4453
4454 cur_arg = 2;
4455 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4456 tcpcheck->action = TCPCHK_ACT_CONNECT;
4457
4458 /* parsing each parameters to fill up the rule */
4459 while (*(ptr_arg = args[cur_arg])) {
4460 /* tcp port */
4461 if (strcmp(args[cur_arg], "port") == 0) {
4462 if ( (atol(args[cur_arg + 1]) > 65535) ||
4463 (atol(args[cur_arg + 1]) < 1) ){
4464 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4465 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
4468 }
4469 tcpcheck->port = atol(args[cur_arg + 1]);
4470 cur_arg += 2;
4471 }
4472 /* send proxy protocol */
4473 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4474 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4475 cur_arg++;
4476 }
4477#ifdef USE_OPENSSL
4478 else if (strcmp(args[cur_arg], "ssl") == 0) {
4479 curproxy->options |= PR_O_TCPCHK_SSL;
4480 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4481 cur_arg++;
4482 }
4483#endif /* USE_OPENSSL */
4484 else {
4485#ifdef USE_OPENSSL
4486 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4487#else /* USE_OPENSSL */
4488 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4489#endif /* USE_OPENSSL */
4490 file, linenum, args[0], args[1], args[cur_arg]);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
4494
4495 }
4496
4497 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4498 }
4499 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004500 if (! *(args[2]) ) {
4501 /* SEND string expected */
4502 Alert("parsing [%s:%d] : '%s %s %s' expects <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
4509 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4510
4511 tcpcheck->action = TCPCHK_ACT_SEND;
4512 tcpcheck->string_len = strlen(args[2]);
4513 tcpcheck->string = strdup(args[2]);
4514 tcpcheck->expect_regex = NULL;
4515
4516 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4517 }
4518 }
4519 else if (strcmp(args[1], "send-binary") == 0) {
4520 if (! *(args[2]) ) {
4521 /* SEND binary string expected */
4522 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4523 file, linenum, args[0], args[1], args[2]);
4524 err_code |= ERR_ALERT | ERR_FATAL;
4525 goto out;
4526 } else {
4527 struct tcpcheck_rule *tcpcheck;
4528 char *err = NULL;
4529
4530 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4531
4532 tcpcheck->action = TCPCHK_ACT_SEND;
4533 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4534 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4535 file, linenum, args[0], args[1], args[2], err);
4536 err_code |= ERR_ALERT | ERR_FATAL;
4537 goto out;
4538 }
4539 tcpcheck->expect_regex = NULL;
4540
4541 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4542 }
4543 }
4544 else if (strcmp(args[1], "expect") == 0) {
4545 const char *ptr_arg;
4546 int cur_arg;
4547 int inverse = 0;
4548
4549 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4550 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4551 err_code |= ERR_ALERT | ERR_FATAL;
4552 goto out;
4553 }
4554
4555 cur_arg = 2;
4556 /* consider exclamation marks, sole or at the beginning of a word */
4557 while (*(ptr_arg = args[cur_arg])) {
4558 while (*ptr_arg == '!') {
4559 inverse = !inverse;
4560 ptr_arg++;
4561 }
4562 if (*ptr_arg)
4563 break;
4564 cur_arg++;
4565 }
4566 /* now ptr_arg points to the beginning of a word past any possible
4567 * exclamation mark, and cur_arg is the argument which holds this word.
4568 */
4569 if (strcmp(ptr_arg, "binary") == 0) {
4570 if (!*(args[cur_arg + 1])) {
4571 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4572 file, linenum, args[0], args[1], ptr_arg);
4573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
4575 }
4576 struct tcpcheck_rule *tcpcheck;
4577 char *err = NULL;
4578
4579 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4580
4581 tcpcheck->action = TCPCHK_ACT_EXPECT;
4582 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4583 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4584 file, linenum, args[0], args[1], args[2], err);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588 tcpcheck->expect_regex = NULL;
4589 tcpcheck->inverse = inverse;
4590
4591 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4592 }
4593 else if (strcmp(ptr_arg, "string") == 0) {
4594 if (!*(args[cur_arg + 1])) {
4595 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4596 file, linenum, args[0], args[1], ptr_arg);
4597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599 }
4600 struct tcpcheck_rule *tcpcheck;
4601
4602 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4603
4604 tcpcheck->action = TCPCHK_ACT_EXPECT;
4605 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4606 tcpcheck->string = strdup(args[cur_arg + 1]);
4607 tcpcheck->expect_regex = NULL;
4608 tcpcheck->inverse = inverse;
4609
4610 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4611 }
4612 else if (strcmp(ptr_arg, "rstring") == 0) {
4613 if (!*(args[cur_arg + 1])) {
4614 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4615 file, linenum, args[0], args[1], ptr_arg);
4616 err_code |= ERR_ALERT | ERR_FATAL;
4617 goto out;
4618 }
4619 struct tcpcheck_rule *tcpcheck;
4620
4621 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4622
4623 tcpcheck->action = TCPCHK_ACT_EXPECT;
4624 tcpcheck->string_len = 0;
4625 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004626 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4627 error = NULL;
4628 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4629 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4630 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4631 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004632 err_code |= ERR_ALERT | ERR_FATAL;
4633 goto out;
4634 }
4635 tcpcheck->inverse = inverse;
4636
4637 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4638 }
4639 else {
4640 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4641 file, linenum, args[0], args[1], ptr_arg);
4642 err_code |= ERR_ALERT | ERR_FATAL;
4643 goto out;
4644 }
4645 }
4646 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004647 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
4650 }
4651 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004652 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004653 if (curproxy == &defproxy) {
4654 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_ALERT | ERR_FATAL;
4656 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004657 }
4658
Willy Tarreaub80c2302007-11-30 20:51:32 +01004659 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004660 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004661
4662 if (strcmp(args[1], "fail") == 0) {
4663 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004664 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004665 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4666 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004669 }
4670
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004671 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4672 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4673 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004676 }
4677 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4678 }
4679 else {
4680 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004683 }
4684 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004685#ifdef TPROXY
4686 else if (!strcmp(args[0], "transparent")) {
4687 /* enable transparent proxy connections */
4688 curproxy->options |= PR_O_TRANSP;
4689 }
4690#endif
4691 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004692 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004693 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004694
Willy Tarreaubaaee002006-06-26 02:48:02 +02004695 if (*(args[1]) == 0) {
4696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004699 }
4700 curproxy->maxconn = atol(args[1]);
4701 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004702 else if (!strcmp(args[0], "backlog")) { /* backlog */
4703 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004705
4706 if (*(args[1]) == 0) {
4707 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004710 }
4711 curproxy->backlog = atol(args[1]);
4712 }
Willy Tarreau86034312006-12-29 00:10:33 +01004713 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004715 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004716
Willy Tarreau86034312006-12-29 00:10:33 +01004717 if (*(args[1]) == 0) {
4718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004719 err_code |= ERR_ALERT | ERR_FATAL;
4720 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004721 }
4722 curproxy->fullconn = atol(args[1]);
4723 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004724 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4725 if (*(args[1]) == 0) {
4726 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004730 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4731 if (err) {
4732 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4733 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004736 }
4737 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004738 }
4739 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004740 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004741 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004742 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004743
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 if (curproxy == &defproxy) {
4745 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004746 err_code |= ERR_ALERT | ERR_FATAL;
4747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004748 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004749 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004751
Willy Tarreau902636f2013-03-10 19:44:48 +01004752 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004753 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004754 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004755 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004756 goto out;
4757 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004758
4759 proto = protocol_by_family(sk->ss_family);
4760 if (!proto || !proto->connect) {
4761 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4762 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
4765 }
4766
4767 if (port1 != port2) {
4768 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4769 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004770 err_code |= ERR_ALERT | ERR_FATAL;
4771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004772 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004773
4774 if (!port1) {
4775 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4776 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004777 err_code |= ERR_ALERT | ERR_FATAL;
4778 goto out;
4779 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004780
Willy Tarreaud5191e72010-02-09 20:50:45 +01004781 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004782 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004783 }
4784 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004786 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004787
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004788 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4789 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004790 err_code |= ERR_ALERT | ERR_FATAL;
4791 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004792 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004793 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004794 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004795 /**
4796 * The syntax for hash-type config element is
4797 * hash-type {map-based|consistent} [[<algo>] avalanche]
4798 *
4799 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4800 */
4801 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004802
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004803 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4804 err_code |= ERR_WARN;
4805
4806 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004807 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4808 }
4809 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004810 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4811 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004812 else if (strcmp(args[1], "avalanche") == 0) {
4813 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]);
4814 err_code |= ERR_ALERT | ERR_FATAL;
4815 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004816 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004817 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004818 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004819 err_code |= ERR_ALERT | ERR_FATAL;
4820 goto out;
4821 }
Bhaskar98634f02013-10-29 23:30:51 -04004822
4823 /* set the hash function to use */
4824 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004825 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004826 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004827
4828 /* if consistent with no argument, then avalanche modifier is also applied */
4829 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4830 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004831 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004832 /* set the hash function */
4833 if (!strcmp(args[2], "sdbm")) {
4834 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4835 }
4836 else if (!strcmp(args[2], "djb2")) {
4837 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004838 } else if (!strcmp(args[2], "wt6")) {
4839 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004840 }
4841 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004842 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 -05004843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
4845 }
4846
4847 /* set the hash modifier */
4848 if (!strcmp(args[3], "avalanche")) {
4849 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4850 }
4851 else if (*args[3]) {
4852 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4853 err_code |= ERR_ALERT | ERR_FATAL;
4854 goto out;
4855 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004856 }
William Lallemanda73203e2012-03-12 12:48:57 +01004857 }
William Lallemanda73203e2012-03-12 12:48:57 +01004858 else if (strcmp(args[0], "unique-id-format") == 0) {
4859 if (!*(args[1])) {
4860 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4861 err_code |= ERR_ALERT | ERR_FATAL;
4862 goto out;
4863 }
William Lallemand3203ff42012-11-11 17:30:56 +01004864 if (*(args[2])) {
4865 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004869 free(curproxy->conf.uniqueid_format_string);
4870 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004871
Willy Tarreau62a61232013-04-12 18:13:46 +02004872 free(curproxy->conf.uif_file);
4873 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4874 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004875 }
William Lallemanda73203e2012-03-12 12:48:57 +01004876
4877 else if (strcmp(args[0], "unique-id-header") == 0) {
4878 if (!*(args[1])) {
4879 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4880 err_code |= ERR_ALERT | ERR_FATAL;
4881 goto out;
4882 }
4883 free(curproxy->header_unique_id);
4884 curproxy->header_unique_id = strdup(args[1]);
4885 }
4886
William Lallemand723b73a2012-02-08 16:37:49 +01004887 else if (strcmp(args[0], "log-format") == 0) {
4888 if (!*(args[1])) {
4889 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4890 err_code |= ERR_ALERT | ERR_FATAL;
4891 goto out;
4892 }
William Lallemand3203ff42012-11-11 17:30:56 +01004893 if (*(args[2])) {
4894 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4895 err_code |= ERR_ALERT | ERR_FATAL;
4896 goto out;
4897 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004898
Willy Tarreau62a61232013-04-12 18:13:46 +02004899 if (curproxy->conf.logformat_string != default_http_log_format &&
4900 curproxy->conf.logformat_string != default_tcp_log_format &&
4901 curproxy->conf.logformat_string != clf_http_log_format)
4902 free(curproxy->conf.logformat_string);
4903 curproxy->conf.logformat_string = strdup(args[1]);
4904
4905 free(curproxy->conf.lfs_file);
4906 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4907 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004908
4909 /* get a chance to improve log-format error reporting by
4910 * reporting the correct line-number when possible.
4911 */
4912 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4913 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4914 file, linenum, curproxy->id);
4915 err_code |= ERR_WARN;
4916 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004917 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01004918 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
4919 if (*(args[1]) == 0) {
4920 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
4921 err_code |= ERR_ALERT | ERR_FATAL;
4922 goto out;
4923 }
4924 free(curproxy->log_tag);
4925 curproxy->log_tag = strdup(args[1]);
4926 }
William Lallemand0f99e342011-10-12 17:50:54 +02004927 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4928 /* delete previous herited or defined syslog servers */
4929 struct logsrv *back;
4930
4931 if (*(args[1]) != 0) {
4932 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
4935 }
4936
William Lallemand723b73a2012-02-08 16:37:49 +01004937 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4938 LIST_DEL(&tmplogsrv->list);
4939 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004940 }
4941 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004942 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004943 struct logsrv *logsrv;
4944
Willy Tarreaubaaee002006-06-26 02:48:02 +02004945 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004946 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004947 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004948 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004949 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004950 LIST_INIT(&node->list);
4951 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4952 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004953 }
4954 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004955 struct sockaddr_storage *sk;
4956 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02004957 int arg = 0;
4958 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004959
4960 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004961
Willy Tarreau18324f52014-06-27 18:10:07 +02004962 /* just after the address, a length may be specified */
4963 if (strcmp(args[arg+2], "len") == 0) {
4964 len = atoi(args[arg+3]);
4965 if (len < 80 || len > 65535) {
4966 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4967 file, linenum, args[arg+3]);
4968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
4970 }
4971 logsrv->maxlen = len;
4972
4973 /* skip these two args */
4974 arg += 2;
4975 }
4976 else
4977 logsrv->maxlen = MAX_SYSLOG_LEN;
4978
4979 if (logsrv->maxlen > global.max_syslog_len) {
4980 global.max_syslog_len = logsrv->maxlen;
4981 logline = realloc(logline, global.max_syslog_len + 1);
4982 }
4983
4984 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004985 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004986 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004987 err_code |= ERR_ALERT | ERR_FATAL;
4988 goto out;
4989
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
4991
William Lallemand0f99e342011-10-12 17:50:54 +02004992 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02004993 if (*(args[arg+3])) {
4994 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004995 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02004996 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
4999
Willy Tarreaubaaee002006-06-26 02:48:02 +02005000 }
5001 }
5002
William Lallemand0f99e342011-10-12 17:50:54 +02005003 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005004 if (*(args[arg+4])) {
5005 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005006 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005007 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005011 }
5012 }
5013
Willy Tarreau902636f2013-03-10 19:44:48 +01005014 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005015 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005016 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005017 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005018 goto out;
5019 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005020
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005021 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005022
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005023 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005024 if (port1 != port2) {
5025 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5026 file, linenum, args[0], args[1]);
5027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
5029 }
5030
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005031 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005032 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 }
William Lallemand0f99e342011-10-12 17:50:54 +02005034
5035 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005036 }
5037 else {
5038 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5039 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005042 }
5043 }
5044 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005045 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005046 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005047 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005048 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005049
Willy Tarreau977b8e42006-12-29 14:19:17 +01005050 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005052
Willy Tarreaubaaee002006-06-26 02:48:02 +02005053 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005054 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5055 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005056 err_code |= ERR_ALERT | ERR_FATAL;
5057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005058 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005059
5060 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005061 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5062 free(curproxy->conn_src.iface_name);
5063 curproxy->conn_src.iface_name = NULL;
5064 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005065
Willy Tarreau902636f2013-03-10 19:44:48 +01005066 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005067 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005068 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005069 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005070 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005071 goto out;
5072 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005073
5074 proto = protocol_by_family(sk->ss_family);
5075 if (!proto || !proto->connect) {
5076 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005077 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
5080 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005081
5082 if (port1 != port2) {
5083 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5084 file, linenum, args[0], args[1]);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
5088
Willy Tarreauef9a3602012-12-08 22:29:20 +01005089 curproxy->conn_src.source_addr = *sk;
5090 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005091
5092 cur_arg = 2;
5093 while (*(args[cur_arg])) {
5094 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005095#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5096#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005097 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005098 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5099 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005100 err_code |= ERR_ALERT | ERR_FATAL;
5101 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005102 }
5103#endif
5104 if (!*args[cur_arg + 1]) {
5105 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5106 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005109 }
5110
5111 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005112 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5113 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005114 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005115 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5116 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005117 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5118 char *name, *end;
5119
5120 name = args[cur_arg+1] + 7;
5121 while (isspace(*name))
5122 name++;
5123
5124 end = name;
5125 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5126 end++;
5127
Willy Tarreauef9a3602012-12-08 22:29:20 +01005128 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5129 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5130 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5131 curproxy->conn_src.bind_hdr_len = end - name;
5132 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5133 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5134 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005135
5136 /* now look for an occurrence number */
5137 while (isspace(*end))
5138 end++;
5139 if (*end == ',') {
5140 end++;
5141 name = end;
5142 if (*end == '-')
5143 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005144 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005145 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005146 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005147 }
5148
Willy Tarreauef9a3602012-12-08 22:29:20 +01005149 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005150 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5151 " occurrences values smaller than %d.\n",
5152 file, linenum, MAX_HDR_HISTORY);
5153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
5155 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005156 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005157 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005158
Willy Tarreau902636f2013-03-10 19:44:48 +01005159 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005160 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005161 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005162 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005163 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005164 goto out;
5165 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005166
5167 proto = protocol_by_family(sk->ss_family);
5168 if (!proto || !proto->connect) {
5169 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5170 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
5173 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005174
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005175 if (port1 != port2) {
5176 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5177 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
5180 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005181 curproxy->conn_src.tproxy_addr = *sk;
5182 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005183 }
5184 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005185#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005186 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005187#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005188#else /* no TPROXY support */
5189 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005190 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005191 err_code |= ERR_ALERT | ERR_FATAL;
5192 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005193#endif
5194 cur_arg += 2;
5195 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005196 }
5197
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005198 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5199#ifdef SO_BINDTODEVICE
5200 if (!*args[cur_arg + 1]) {
5201 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5202 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005205 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005206 free(curproxy->conn_src.iface_name);
5207 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5208 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005209 global.last_checks |= LSTCHK_NETADM;
5210#else
5211 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5212 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005215#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005216 cur_arg += 2;
5217 continue;
5218 }
5219 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005220 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005221 err_code |= ERR_ALERT | ERR_FATAL;
5222 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005223 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005225 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5226 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5227 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005233 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5234 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005238
5239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005241 args[0], args[1], args[2], (const char **)args+3);
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 }
5245 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a 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_REMOVE, 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 Tarreaubaaee002006-06-26 02:48:02 +02005251 }
5252 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
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_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005258 }
5259 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005260 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005261 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005262 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005263 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005265 }
5266 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005267 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005268 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005269 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005270 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005273 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005274 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005275 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005276 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005277 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005278 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005279 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005280 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005281 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005282 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005283 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005284 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005285 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005286
5287 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5288 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 +01005289 }
5290 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005291 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005292 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005293 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005294 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005295 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005296
5297 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5298 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 +01005299 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5303 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005307
5308 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005309 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005310 args[0], args[1], args[2], (const char **)args+3);
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 }
5314 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a 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_REMOVE, 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 Tarreaubaaee002006-06-26 02:48:02 +02005320 }
5321 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005322 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005323 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005324 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005325 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 }
5328 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005329 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005330 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005331 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005332 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 }
5335 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005336 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005337 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005338 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005342 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005344 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005345 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005347 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005348 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005350 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005351
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 if (curproxy == &defproxy) {
5353 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005354 err_code |= ERR_ALERT | ERR_FATAL;
5355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005357 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 if (*(args[1]) == 0) {
5361 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005362 err_code |= ERR_ALERT | ERR_FATAL;
5363 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005364 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005365
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005366 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005367 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5368 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5369 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
5372 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005373 err_code |= warnif_cond_conflicts(cond,
5374 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5375 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005376 }
5377 else if (*args[2]) {
5378 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5379 file, linenum, args[0], args[2]);
5380 err_code |= ERR_ALERT | ERR_FATAL;
5381 goto out;
5382 }
5383
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005384 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005385 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005386 wl->s = strdup(args[1]);
5387 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005388 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
5390 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005397
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, 0,
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], "rspdel")) { /* delete response header from a regex */
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, 0,
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], "rspdeny")) { /* block response header from a regex */
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, 0,
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], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005419 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5421 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005424 }
5425
Willy Tarreauade5ec42010-01-28 19:33:49 +01005426 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005427 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005428 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005429 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 }
5432 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005433 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005434 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005435 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005436 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005437 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 }
5439 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005440 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005441 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005442 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005443 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005445 }
5446 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005447 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005448
Willy Tarreaubaaee002006-06-26 02:48:02 +02005449 if (curproxy == &defproxy) {
5450 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005454 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005455 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005456
Willy Tarreaubaaee002006-06-26 02:48:02 +02005457 if (*(args[1]) == 0) {
5458 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 }
5462
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005463 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005464 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5465 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5466 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
5469 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005470 err_code |= warnif_cond_conflicts(cond,
5471 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5472 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005473 }
5474 else if (*args[2]) {
5475 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5476 file, linenum, args[0], args[2]);
5477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005481 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005482 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005483 wl->s = strdup(args[1]);
5484 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005485 }
5486 else if (!strcmp(args[0], "errorloc") ||
5487 !strcmp(args[0], "errorloc302") ||
5488 !strcmp(args[0], "errorloc303")) { /* error location */
5489 int errnum, errlen;
5490 char *err;
5491
Willy Tarreau977b8e42006-12-29 14:19:17 +01005492 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005493 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005494
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005496 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005497 err_code |= ERR_ALERT | ERR_FATAL;
5498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005499 }
5500
5501 errnum = atol(args[1]);
5502 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005503 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5504 err = malloc(errlen);
5505 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005506 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005507 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5508 err = malloc(errlen);
5509 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
5511
Willy Tarreau0f772532006-12-23 20:51:41 +01005512 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5513 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005514 chunk_destroy(&curproxy->errmsg[rc]);
5515 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005516 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005519
5520 if (rc >= HTTP_ERR_SIZE) {
5521 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5522 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 free(err);
5524 }
5525 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005526 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5527 int errnum, errlen, fd;
5528 char *err;
5529 struct stat stat;
5530
5531 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005532 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005533
5534 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005535 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005538 }
5539
5540 fd = open(args[2], O_RDONLY);
5541 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5542 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5543 file, linenum, args[2], args[1]);
5544 if (fd >= 0)
5545 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005546 err_code |= ERR_ALERT | ERR_FATAL;
5547 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005548 }
5549
Willy Tarreau27a674e2009-08-17 07:23:33 +02005550 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005551 errlen = stat.st_size;
5552 } else {
5553 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005554 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005555 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005556 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005557 }
5558
5559 err = malloc(errlen); /* malloc() must succeed during parsing */
5560 errnum = read(fd, err, errlen);
5561 if (errnum != errlen) {
5562 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5563 file, linenum, args[2], args[1]);
5564 close(fd);
5565 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005568 }
5569 close(fd);
5570
5571 errnum = atol(args[1]);
5572 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5573 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005574 chunk_destroy(&curproxy->errmsg[rc]);
5575 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005576 break;
5577 }
5578 }
5579
5580 if (rc >= HTTP_ERR_SIZE) {
5581 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5582 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005583 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005584 free(err);
5585 }
5586 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005587 else if (!strcmp(args[0], "compression")) {
5588 struct comp *comp;
5589 if (curproxy->comp == NULL) {
5590 comp = calloc(1, sizeof(struct comp));
5591 curproxy->comp = comp;
5592 } else {
5593 comp = curproxy->comp;
5594 }
5595
5596 if (!strcmp(args[1], "algo")) {
5597 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005598 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005599
William Lallemand82fe75c2012-10-23 10:25:10 +02005600 cur_arg = 2;
5601 if (!*args[cur_arg]) {
5602 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5603 file, linenum, args[0]);
5604 err_code |= ERR_ALERT | ERR_FATAL;
5605 goto out;
5606 }
5607 while (*(args[cur_arg])) {
5608 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5609 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5610 file, linenum, args[0], args[cur_arg]);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
William Lallemand552df672012-11-07 13:21:47 +01005614 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5615 curproxy->comp->algos->end(&ctx);
5616 } else {
5617 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5618 file, linenum, args[0], args[cur_arg]);
5619 err_code |= ERR_ALERT | ERR_FATAL;
5620 goto out;
5621 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005622 cur_arg ++;
5623 continue;
5624 }
5625 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005626 else if (!strcmp(args[1], "offload")) {
5627 comp->offload = 1;
5628 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005629 else if (!strcmp(args[1], "type")) {
5630 int cur_arg;
5631 cur_arg = 2;
5632 if (!*args[cur_arg]) {
5633 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5634 file, linenum, args[0]);
5635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
5637 }
5638 while (*(args[cur_arg])) {
5639 comp_append_type(comp, args[cur_arg]);
5640 cur_arg ++;
5641 continue;
5642 }
5643 }
5644 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005645 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005646 file, linenum, args[0]);
5647 err_code |= ERR_ALERT | ERR_FATAL;
5648 goto out;
5649 }
5650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005652 struct cfg_kw_list *kwl;
5653 int index;
5654
5655 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5656 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5657 if (kwl->kw[index].section != CFG_LISTEN)
5658 continue;
5659 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5660 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005661 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005662 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005663 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005664 err_code |= ERR_ALERT | ERR_FATAL;
5665 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005666 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005667 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005668 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005669 err_code |= ERR_WARN;
5670 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005671 }
Willy Tarreau93893792009-07-23 13:19:11 +02005672 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005673 }
5674 }
5675 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005676
Willy Tarreau6daf3432008-01-22 16:44:08 +01005677 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 }
Willy Tarreau93893792009-07-23 13:19:11 +02005681 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005682 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005683 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684}
5685
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005686int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005687cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5688{
5689#ifdef CONFIG_HAP_NS
5690 const char *err;
5691 const char *item = args[0];
5692
5693 if (!strcmp(item, "namespace_list")) {
5694 return 0;
5695 }
5696 else if (!strcmp(item, "namespace")) {
5697 size_t idx = 1;
5698 const char *current;
5699 while (*(current = args[idx++])) {
5700 err = invalid_char(current);
5701 if (err) {
5702 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5703 file, linenum, *err, item, current);
5704 return ERR_ALERT | ERR_FATAL;
5705 }
5706
5707 if (netns_store_lookup(current, strlen(current))) {
5708 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5709 file, linenum, current);
5710 return ERR_ALERT | ERR_FATAL;
5711 }
5712 if (!netns_store_insert(current)) {
5713 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5714 file, linenum, current);
5715 return ERR_ALERT | ERR_FATAL;
5716 }
5717 }
5718 }
5719
5720 return 0;
5721#else
5722 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5723 file, linenum);
5724 return ERR_ALERT | ERR_FATAL;
5725#endif
5726}
5727
5728int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005729cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5730{
5731
5732 int err_code = 0;
5733 const char *err;
5734
5735 if (!strcmp(args[0], "userlist")) { /* new userlist */
5736 struct userlist *newul;
5737
5738 if (!*args[1]) {
5739 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5740 file, linenum, args[0]);
5741 err_code |= ERR_ALERT | ERR_FATAL;
5742 goto out;
5743 }
5744
5745 err = invalid_char(args[1]);
5746 if (err) {
5747 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5748 file, linenum, *err, args[0], args[1]);
5749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
5751 }
5752
5753 for (newul = userlist; newul; newul = newul->next)
5754 if (!strcmp(newul->name, args[1])) {
5755 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5756 file, linenum, args[1]);
5757 err_code |= ERR_WARN;
5758 goto out;
5759 }
5760
5761 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5762 if (!newul) {
5763 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5764 err_code |= ERR_ALERT | ERR_ABORT;
5765 goto out;
5766 }
5767
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005768 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005769 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005770 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5771 err_code |= ERR_ALERT | ERR_ABORT;
5772 goto out;
5773 }
5774
5775 newul->next = userlist;
5776 userlist = newul;
5777
5778 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005779 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005780 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005781 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005782
5783 if (!*args[1]) {
5784 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5785 file, linenum, args[0]);
5786 err_code |= ERR_ALERT | ERR_FATAL;
5787 goto out;
5788 }
5789
5790 err = invalid_char(args[1]);
5791 if (err) {
5792 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5793 file, linenum, *err, args[0], args[1]);
5794 err_code |= ERR_ALERT | ERR_FATAL;
5795 goto out;
5796 }
5797
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005798 for (ag = userlist->groups; ag; ag = ag->next)
5799 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005800 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5801 file, linenum, args[1], userlist->name);
5802 err_code |= ERR_ALERT;
5803 goto out;
5804 }
5805
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005806 ag = calloc(1, sizeof(*ag));
5807 if (!ag) {
5808 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5809 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005810 goto out;
5811 }
5812
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005813 ag->name = strdup(args[1]);
5814 if (!ag) {
5815 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5816 err_code |= ERR_ALERT | ERR_ABORT;
5817 goto out;
5818 }
5819
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005820 cur_arg = 2;
5821
5822 while (*args[cur_arg]) {
5823 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005824 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005825 cur_arg += 2;
5826 continue;
5827 } else {
5828 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5829 file, linenum, args[0]);
5830 err_code |= ERR_ALERT | ERR_FATAL;
5831 goto out;
5832 }
5833 }
5834
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005835 ag->next = userlist->groups;
5836 userlist->groups = ag;
5837
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005838 } else if (!strcmp(args[0], "user")) { /* new user */
5839 struct auth_users *newuser;
5840 int cur_arg;
5841
5842 if (!*args[1]) {
5843 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5844 file, linenum, args[0]);
5845 err_code |= ERR_ALERT | ERR_FATAL;
5846 goto out;
5847 }
5848
5849 for (newuser = userlist->users; newuser; newuser = newuser->next)
5850 if (!strcmp(newuser->user, args[1])) {
5851 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5852 file, linenum, args[1], userlist->name);
5853 err_code |= ERR_ALERT;
5854 goto out;
5855 }
5856
5857 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5858 if (!newuser) {
5859 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5860 err_code |= ERR_ALERT | ERR_ABORT;
5861 goto out;
5862 }
5863
5864 newuser->user = strdup(args[1]);
5865
5866 newuser->next = userlist->users;
5867 userlist->users = newuser;
5868
5869 cur_arg = 2;
5870
5871 while (*args[cur_arg]) {
5872 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02005873#ifdef CONFIG_HAP_CRYPT
5874 if (!crypt("", args[cur_arg + 1])) {
5875 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5876 file, linenum, newuser->user);
5877 err_code |= ERR_ALERT | ERR_FATAL;
5878 goto out;
5879 }
5880#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005881 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5882 file, linenum);
5883 err_code |= ERR_ALERT;
5884#endif
5885 newuser->pass = strdup(args[cur_arg + 1]);
5886 cur_arg += 2;
5887 continue;
5888 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5889 newuser->pass = strdup(args[cur_arg + 1]);
5890 newuser->flags |= AU_O_INSECURE;
5891 cur_arg += 2;
5892 continue;
5893 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005894 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005895 cur_arg += 2;
5896 continue;
5897 } else {
5898 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5899 file, linenum, args[0]);
5900 err_code |= ERR_ALERT | ERR_FATAL;
5901 goto out;
5902 }
5903 }
5904 } else {
5905 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5906 err_code |= ERR_ALERT | ERR_FATAL;
5907 }
5908
5909out:
5910 return err_code;
5911}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005912
5913/*
5914 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005915 * Returns the error code, 0 if OK, or any combination of :
5916 * - ERR_ABORT: must abort ASAP
5917 * - ERR_FATAL: we can continue parsing but not start the service
5918 * - ERR_WARN: a warning has been emitted
5919 * - ERR_ALERT: an alert has been emitted
5920 * Only the two first ones can stop processing, the two others are just
5921 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005923int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005925 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005926 FILE *f;
5927 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005928 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005929 struct cfg_section *cs = NULL;
5930 struct cfg_section *ics;
5931
5932 /* Register internal sections */
5933 if (!cfg_register_section("listen", cfg_parse_listen) ||
5934 !cfg_register_section("frontend", cfg_parse_listen) ||
5935 !cfg_register_section("backend", cfg_parse_listen) ||
5936 !cfg_register_section("ruleset", cfg_parse_listen) ||
5937 !cfg_register_section("defaults", cfg_parse_listen) ||
5938 !cfg_register_section("global", cfg_parse_global) ||
5939 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005940 !cfg_register_section("peers", cfg_parse_peers) ||
5941 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005942 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005943
Willy Tarreaubaaee002006-06-26 02:48:02 +02005944 if ((f=fopen(file,"r")) == NULL)
5945 return -1;
5946
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005947 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005948 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005949 char *end;
5950 char *args[MAX_LINE_ARGS + 1];
5951 char *line = thisline;
5952
Willy Tarreaubaaee002006-06-26 02:48:02 +02005953 linenum++;
5954
5955 end = line + strlen(line);
5956
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005957 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5958 /* Check if we reached the limit and the last char is not \n.
5959 * Watch out for the last line without the terminating '\n'!
5960 */
5961 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005962 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005963 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005964 }
5965
Willy Tarreaubaaee002006-06-26 02:48:02 +02005966 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005967 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968 line++;
5969
5970 arg = 0;
5971 args[arg] = line;
5972
5973 while (*line && arg < MAX_LINE_ARGS) {
5974 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5975 * C equivalent value. Other combinations left unchanged (eg: \1).
5976 */
5977 if (*line == '\\') {
5978 int skip = 0;
5979 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5980 *line = line[1];
5981 skip = 1;
5982 }
5983 else if (line[1] == 'r') {
5984 *line = '\r';
5985 skip = 1;
5986 }
5987 else if (line[1] == 'n') {
5988 *line = '\n';
5989 skip = 1;
5990 }
5991 else if (line[1] == 't') {
5992 *line = '\t';
5993 skip = 1;
5994 }
5995 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005996 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 unsigned char hex1, hex2;
5998 hex1 = toupper(line[2]) - '0';
5999 hex2 = toupper(line[3]) - '0';
6000 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6001 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6002 *line = (hex1<<4) + hex2;
6003 skip = 3;
6004 }
6005 else {
6006 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006007 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006008 }
6009 }
6010 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006011 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 end -= skip;
6013 }
6014 line++;
6015 }
6016 else if (*line == '#' || *line == '\n' || *line == '\r') {
6017 /* end of string, end of loop */
6018 *line = 0;
6019 break;
6020 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006021 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006022 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006023 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006024 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006025 line++;
6026 args[++arg] = line;
6027 }
6028 else {
6029 line++;
6030 }
6031 }
6032
6033 /* empty line */
6034 if (!**args)
6035 continue;
6036
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006037 if (*line) {
6038 /* we had to stop due to too many args.
6039 * Let's terminate the string, print the offending part then cut the
6040 * last arg.
6041 */
6042 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6043 line++;
6044 *line = '\0';
6045
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006046 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006047 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006048 err_code |= ERR_ALERT | ERR_FATAL;
6049 args[arg] = line;
6050 }
6051
Willy Tarreau540abe42007-05-02 20:50:16 +02006052 /* zero out remaining args and ensure that at least one entry
6053 * is zeroed out.
6054 */
6055 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006056 args[arg] = line;
6057 }
6058
Willy Tarreau3842f002009-06-14 11:39:52 +02006059 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006060 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006061 char *tmp;
6062
Willy Tarreau3842f002009-06-14 11:39:52 +02006063 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006064 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006065 for (arg=0; *args[arg+1]; arg++)
6066 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006067 *tmp = '\0'; // fix the next arg to \0
6068 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006069 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006070 else if (!strcmp(args[0], "default")) {
6071 kwm = KWM_DEF;
6072 for (arg=0; *args[arg+1]; arg++)
6073 args[arg] = args[arg+1]; // shift args after inversion
6074 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006075
William Lallemand0f99e342011-10-12 17:50:54 +02006076 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6077 strcmp(args[0], "log") != 0) {
6078 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006079 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006080 }
6081
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006082 /* detect section start */
6083 list_for_each_entry(ics, &sections, list) {
6084 if (strcmp(args[0], ics->section_name) == 0) {
6085 cursection = ics->section_name;
6086 cs = ics;
6087 break;
6088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006089 }
6090
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006092 if (cs)
6093 err_code |= cs->section_parser(file, linenum, args, kwm);
6094 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006095 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006096 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006097 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006098
6099 if (err_code & ERR_ABORT)
6100 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006102 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006103 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006104 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006105}
6106
Willy Tarreau64ab6072014-09-16 12:17:36 +02006107/* This function propagates processes from frontend <from> to backend <to> so
6108 * that it is always guaranteed that a backend pointed to by a frontend is
6109 * bound to all of its processes. After that, if the target is a "listen"
6110 * instance, the function recursively descends the target's own targets along
6111 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6112 * checked first to ensure that <to> is already bound to all processes of
6113 * <from>, there is no risk of looping and we ensure to follow the shortest
6114 * path to the destination.
6115 *
6116 * It is possible to set <to> to NULL for the first call so that the function
6117 * takes care of visiting the initial frontend in <from>.
6118 *
6119 * It is important to note that the function relies on the fact that all names
6120 * have already been resolved.
6121 */
6122void propagate_processes(struct proxy *from, struct proxy *to)
6123{
6124 struct switching_rule *rule;
6125 struct hdr_exp *exp;
6126
6127 if (to) {
6128 /* check whether we need to go down */
6129 if (from->bind_proc &&
6130 (from->bind_proc & to->bind_proc) == from->bind_proc)
6131 return;
6132
6133 if (!from->bind_proc && !to->bind_proc)
6134 return;
6135
6136 to->bind_proc = from->bind_proc ?
6137 (to->bind_proc | from->bind_proc) : 0;
6138
6139 /* now propagate down */
6140 from = to;
6141 }
6142
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006143 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006144 return;
6145
Willy Tarreauf6b70012014-12-18 14:00:43 +01006146 if (from->state == PR_STSTOPPED)
6147 return;
6148
Willy Tarreau64ab6072014-09-16 12:17:36 +02006149 /* default_backend */
6150 if (from->defbe.be)
6151 propagate_processes(from, from->defbe.be);
6152
6153 /* use_backend */
6154 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006155 if (rule->dynamic)
6156 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006157 to = rule->be.backend;
6158 propagate_processes(from, to);
6159 }
6160
6161 /* reqsetbe */
6162 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6163 if (exp->action != ACT_SETBE)
6164 continue;
6165 to = (struct proxy *)exp->replace;
6166 propagate_processes(from, to);
6167 }
6168}
6169
Willy Tarreaubb925012009-07-23 13:36:36 +02006170/*
6171 * Returns the error code, 0 if OK, or any combination of :
6172 * - ERR_ABORT: must abort ASAP
6173 * - ERR_FATAL: we can continue parsing but not start the service
6174 * - ERR_WARN: a warning has been emitted
6175 * - ERR_ALERT: an alert has been emitted
6176 * Only the two first ones can stop processing, the two others are just
6177 * indicators.
6178 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006179int check_config_validity()
6180{
6181 int cfgerr = 0;
6182 struct proxy *curproxy = NULL;
6183 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006184 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006185 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006186 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006187
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006188 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189 /*
6190 * Now, check for the integrity of all that we have collected.
6191 */
6192
6193 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006194 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006195
Willy Tarreau193b8c62012-11-22 00:17:38 +01006196 if (!global.tune.max_http_hdr)
6197 global.tune.max_http_hdr = MAX_HTTP_HDR;
6198
6199 if (!global.tune.cookie_len)
6200 global.tune.cookie_len = CAPTURE_LEN;
6201
6202 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6203
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006204 /* Post initialisation of the users and groups lists. */
6205 err_code = userlist_postinit();
6206 if (err_code != ERR_NONE)
6207 goto out;
6208
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006209 /* first, we will invert the proxy list order */
6210 curproxy = NULL;
6211 while (proxy) {
6212 struct proxy *next;
6213
6214 next = proxy->next;
6215 proxy->next = curproxy;
6216 curproxy = proxy;
6217 if (!next)
6218 break;
6219 proxy = next;
6220 }
6221
Willy Tarreau419ead82014-09-16 13:41:21 +02006222 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006223 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006224 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006225 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006226 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006227 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006228 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006229 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006230
Willy Tarreau050536d2012-10-04 08:47:34 +02006231 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006232 /* proxy ID not set, use automatic numbering with first
6233 * spare entry starting with next_pxid.
6234 */
6235 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6236 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6237 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006238 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006239 next_pxid++;
6240
Willy Tarreau55ea7572007-06-17 19:56:27 +02006241
Willy Tarreaubaaee002006-06-26 02:48:02 +02006242 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006243 /* ensure we don't keep listeners uselessly bound */
6244 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 continue;
6246 }
6247
Willy Tarreau102df612014-05-07 23:56:38 +02006248 /* Check multi-process mode compatibility for the current proxy */
6249
6250 if (curproxy->bind_proc) {
6251 /* an explicit bind-process was specified, let's check how many
6252 * processes remain.
6253 */
6254 nbproc = popcount(curproxy->bind_proc);
6255
6256 curproxy->bind_proc &= nbits(global.nbproc);
6257 if (!curproxy->bind_proc && nbproc == 1) {
6258 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);
6259 curproxy->bind_proc = 1;
6260 }
6261 else if (!curproxy->bind_proc && nbproc > 1) {
6262 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);
6263 curproxy->bind_proc = 0;
6264 }
6265 }
6266
Willy Tarreau3d209582014-05-09 17:06:11 +02006267 /* check and reduce the bind-proc of each listener */
6268 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6269 unsigned long mask;
6270
6271 if (!bind_conf->bind_proc)
6272 continue;
6273
6274 mask = nbits(global.nbproc);
6275 if (curproxy->bind_proc)
6276 mask &= curproxy->bind_proc;
6277 /* mask cannot be null here thanks to the previous checks */
6278
6279 nbproc = popcount(bind_conf->bind_proc);
6280 bind_conf->bind_proc &= mask;
6281
6282 if (!bind_conf->bind_proc && nbproc == 1) {
6283 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",
6284 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6285 bind_conf->bind_proc = mask & ~(mask - 1);
6286 }
6287 else if (!bind_conf->bind_proc && nbproc > 1) {
6288 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",
6289 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6290 bind_conf->bind_proc = 0;
6291 }
6292 }
6293
Willy Tarreau102df612014-05-07 23:56:38 +02006294 if (global.nbproc > 1 && curproxy->table.peers.name) {
6295 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6296 curproxy->id);
6297 cfgerr++;
6298 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006299
Willy Tarreauff01a212009-03-15 13:46:16 +01006300 switch (curproxy->mode) {
6301 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006302 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006303 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006304 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6305 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006306 cfgerr++;
6307 }
6308
6309 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006310 Warning("config : servers will be ignored for %s '%s'.\n",
6311 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006312 break;
6313
6314 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006315 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006316 break;
6317
6318 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006319 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006320 break;
6321 }
6322
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006323 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006324 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006325 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006326 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6327 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006328 cfgerr++;
6329 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006331 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006332 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6333 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006334 cfgerr++;
6335 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006337 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006338 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6339 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006340 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006341 }
6342 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006343 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006344 /* If no LB algo is set in a backend, and we're not in
6345 * transparent mode, dispatch mode nor proxy mode, we
6346 * want to use balance roundrobin by default.
6347 */
6348 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6349 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006350 }
6351 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006352
Willy Tarreau1620ec32011-08-06 17:05:02 +02006353 if (curproxy->options & PR_O_DISPATCH)
6354 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6355 else if (curproxy->options & PR_O_HTTP_PROXY)
6356 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6357 else if (curproxy->options & PR_O_TRANSP)
6358 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006359
Willy Tarreau1620ec32011-08-06 17:05:02 +02006360 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6361 if (curproxy->options & PR_O_DISABLE404) {
6362 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6363 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6364 err_code |= ERR_WARN;
6365 curproxy->options &= ~PR_O_DISABLE404;
6366 }
6367 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6368 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6369 "send-state", proxy_type_str(curproxy), curproxy->id);
6370 err_code |= ERR_WARN;
6371 curproxy->options &= ~PR_O2_CHK_SNDST;
6372 }
Willy Tarreauef781042010-01-27 11:53:01 +01006373 }
6374
Simon Horman98637e52014-06-20 12:30:16 +09006375 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6376 if (!global.external_check) {
6377 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6378 curproxy->id, "option external-check");
6379 cfgerr++;
6380 }
6381 if (!curproxy->check_command) {
6382 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6383 curproxy->id, "option external-check");
6384 cfgerr++;
6385 }
6386 }
6387
6388 if (curproxy->check_command) {
6389 int clear = 0;
6390 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6391 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6392 "external-check command", proxy_type_str(curproxy), curproxy->id);
6393 err_code |= ERR_WARN;
6394 clear = 1;
6395 }
6396 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6397 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6398 curproxy->id, "external-check command");
6399 cfgerr++;
6400 }
6401 if (clear) {
6402 free(curproxy->check_command);
6403 curproxy->check_command = NULL;
6404 }
6405 }
6406
6407 if (curproxy->check_path) {
6408 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6409 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6410 "external-check path", proxy_type_str(curproxy), curproxy->id);
6411 err_code |= ERR_WARN;
6412 free(curproxy->check_path);
6413 curproxy->check_path = NULL;
6414 }
6415 }
6416
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006417 /* if a default backend was specified, let's find it */
6418 if (curproxy->defbe.name) {
6419 struct proxy *target;
6420
Alex Williams96532db2009-11-01 21:27:13 -05006421 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006422 if (!target) {
6423 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6424 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006425 cfgerr++;
6426 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006427 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6428 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006429 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006430 } else {
6431 free(curproxy->defbe.name);
6432 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006433
6434 /* Emit a warning if this proxy also has some servers */
6435 if (curproxy->srv) {
6436 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6437 curproxy->id);
6438 err_code |= ERR_WARN;
6439 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 }
6441 }
6442
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006443 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006444 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6445 /* map jump target for ACT_SETBE in req_rep chain */
6446 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006447 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006448 struct proxy *target;
6449
Willy Tarreaua496b602006-12-17 23:15:24 +01006450 if (exp->action != ACT_SETBE)
6451 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006452
Alex Williams96532db2009-11-01 21:27:13 -05006453 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006454 if (!target) {
6455 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6456 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006457 cfgerr++;
6458 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006459 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6460 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006461 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006462 } else {
6463 free((void *)exp->replace);
6464 exp->replace = (const char *)target;
6465 }
6466 }
6467 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006468
6469 /* find the target proxy for 'use_backend' rules */
6470 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006471 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006472 struct logformat_node *node;
6473 char *pxname;
6474
6475 /* Try to parse the string as a log format expression. If the result
6476 * of the parsing is only one entry containing a simple string, then
6477 * it's a standard string corresponding to a static rule, thus the
6478 * parsing is cancelled and be.name is restored to be resolved.
6479 */
6480 pxname = rule->be.name;
6481 LIST_INIT(&rule->be.expr);
6482 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6483 curproxy->conf.args.file, curproxy->conf.args.line);
6484 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6485
6486 if (!LIST_ISEMPTY(&rule->be.expr)) {
6487 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6488 rule->dynamic = 1;
6489 free(pxname);
6490 continue;
6491 }
6492 /* simple string: free the expression and fall back to static rule */
6493 free(node->arg);
6494 free(node);
6495 }
6496
6497 rule->dynamic = 0;
6498 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006499
Alex Williams96532db2009-11-01 21:27:13 -05006500 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006501
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006502 if (!target) {
6503 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6504 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006505 cfgerr++;
6506 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006507 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6508 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006509 cfgerr++;
6510 } else {
6511 free((void *)rule->be.name);
6512 rule->be.backend = target;
6513 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006514 }
6515
Willy Tarreau64ab6072014-09-16 12:17:36 +02006516 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006517 list_for_each_entry(srule, &curproxy->server_rules, list) {
6518 struct server *target = findserver(curproxy, srule->srv.name);
6519
6520 if (!target) {
6521 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6522 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6523 cfgerr++;
6524 continue;
6525 }
6526 free((void *)srule->srv.name);
6527 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006528 }
6529
Emeric Brunb982a3d2010-01-04 15:45:53 +01006530 /* find the target table for 'stick' rules */
6531 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6532 struct proxy *target;
6533
Emeric Brun1d33b292010-01-04 15:47:17 +01006534 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6535 if (mrule->flags & STK_IS_STORE)
6536 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6537
Emeric Brunb982a3d2010-01-04 15:45:53 +01006538 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006539 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006540 else
6541 target = curproxy;
6542
6543 if (!target) {
6544 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6545 curproxy->id, mrule->table.name);
6546 cfgerr++;
6547 }
6548 else if (target->table.size == 0) {
6549 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6550 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6551 cfgerr++;
6552 }
Willy Tarreau12785782012-04-27 21:37:17 +02006553 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6554 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006555 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6556 cfgerr++;
6557 }
6558 else {
6559 free((void *)mrule->table.name);
6560 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006561 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006562 }
6563 }
6564
6565 /* find the target table for 'store response' rules */
6566 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6567 struct proxy *target;
6568
Emeric Brun1d33b292010-01-04 15:47:17 +01006569 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6570
Emeric Brunb982a3d2010-01-04 15:45:53 +01006571 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006572 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006573 else
6574 target = curproxy;
6575
6576 if (!target) {
6577 Alert("Proxy '%s': unable to find store table '%s'.\n",
6578 curproxy->id, mrule->table.name);
6579 cfgerr++;
6580 }
6581 else if (target->table.size == 0) {
6582 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6583 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6584 cfgerr++;
6585 }
Willy Tarreau12785782012-04-27 21:37:17 +02006586 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6587 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006588 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6589 cfgerr++;
6590 }
6591 else {
6592 free((void *)mrule->table.name);
6593 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006594 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006595 }
6596 }
6597
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006598 /* find the target table for 'tcp-request' layer 4 rules */
6599 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6600 struct proxy *target;
6601
Willy Tarreaub4c84932013-07-23 19:15:30 +02006602 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006603 continue;
6604
6605 if (trule->act_prm.trk_ctr.table.n)
6606 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6607 else
6608 target = curproxy;
6609
6610 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006611 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6612 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006613 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006614 cfgerr++;
6615 }
6616 else if (target->table.size == 0) {
6617 Alert("Proxy '%s': table '%s' used but not configured.\n",
6618 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6619 cfgerr++;
6620 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006621 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6622 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6623 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 +01006624 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006625 cfgerr++;
6626 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006627 else {
6628 free(trule->act_prm.trk_ctr.table.n);
6629 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006630 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006631 * to pass a list of counters to track and allocate them right here using
6632 * stktable_alloc_data_type().
6633 */
6634 }
6635 }
6636
Willy Tarreaud1f96522010-08-03 19:34:32 +02006637 /* find the target table for 'tcp-request' layer 6 rules */
6638 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6639 struct proxy *target;
6640
Willy Tarreaub4c84932013-07-23 19:15:30 +02006641 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006642 continue;
6643
6644 if (trule->act_prm.trk_ctr.table.n)
6645 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6646 else
6647 target = curproxy;
6648
6649 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006650 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6651 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006652 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006653 cfgerr++;
6654 }
6655 else if (target->table.size == 0) {
6656 Alert("Proxy '%s': table '%s' used but not configured.\n",
6657 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6658 cfgerr++;
6659 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006660 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6661 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6662 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 +01006663 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006664 cfgerr++;
6665 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006666 else {
6667 free(trule->act_prm.trk_ctr.table.n);
6668 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006669 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006670 * to pass a list of counters to track and allocate them right here using
6671 * stktable_alloc_data_type().
6672 */
6673 }
6674 }
6675
Willy Tarreau09448f72014-06-25 18:12:15 +02006676 /* find the target table for 'http-request' layer 7 rules */
6677 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6678 struct proxy *target;
6679
6680 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6681 continue;
6682
6683 if (hrqrule->act_prm.trk_ctr.table.n)
6684 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6685 else
6686 target = curproxy;
6687
6688 if (!target) {
6689 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6690 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6691 http_req_trk_idx(hrqrule->action));
6692 cfgerr++;
6693 }
6694 else if (target->table.size == 0) {
6695 Alert("Proxy '%s': table '%s' used but not configured.\n",
6696 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6697 cfgerr++;
6698 }
6699 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6700 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6701 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6702 http_req_trk_idx(hrqrule->action));
6703 cfgerr++;
6704 }
6705 else {
6706 free(hrqrule->act_prm.trk_ctr.table.n);
6707 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6708 /* Note: if we decide to enhance the track-sc syntax, we may be able
6709 * to pass a list of counters to track and allocate them right here using
6710 * stktable_alloc_data_type().
6711 */
6712 }
6713 }
6714
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006715 /* move any "block" rules at the beginning of the http-request rules */
6716 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6717 /* insert block_rules into http_req_rules at the beginning */
6718 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6719 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6720 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6721 curproxy->http_req_rules.n = curproxy->block_rules.n;
6722 LIST_INIT(&curproxy->block_rules);
6723 }
6724
Emeric Brun32da3c42010-09-23 18:39:19 +02006725 if (curproxy->table.peers.name) {
6726 struct peers *curpeers = peers;
6727
6728 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6729 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6730 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006731 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006732 break;
6733 }
6734 }
6735
6736 if (!curpeers) {
6737 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6738 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006739 free((void *)curproxy->table.peers.name);
6740 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006741 cfgerr++;
6742 }
6743 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006744 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6745 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006746 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006747 cfgerr++;
6748 }
6749 }
6750
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006751 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006752 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006753 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6754 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6755 "proxy", curproxy->id);
6756 cfgerr++;
6757 goto out_uri_auth_compat;
6758 }
6759
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006760 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006761 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006762 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006763 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006764
Willy Tarreau95fa4692010-02-01 13:05:50 +01006765 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6766 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006767
6768 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006769 uri_auth_compat_req[i++] = "realm";
6770 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6771 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006772
Willy Tarreau95fa4692010-02-01 13:05:50 +01006773 uri_auth_compat_req[i++] = "unless";
6774 uri_auth_compat_req[i++] = "{";
6775 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6776 uri_auth_compat_req[i++] = "}";
6777 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006778
Willy Tarreauff011f22011-01-06 17:51:27 +01006779 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6780 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006781 cfgerr++;
6782 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006783 }
6784
Willy Tarreauff011f22011-01-06 17:51:27 +01006785 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006786
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006787 if (curproxy->uri_auth->auth_realm) {
6788 free(curproxy->uri_auth->auth_realm);
6789 curproxy->uri_auth->auth_realm = NULL;
6790 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006791
6792 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006793 }
6794out_uri_auth_compat:
6795
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006796 /* compile the log format */
6797 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006798 if (curproxy->conf.logformat_string != default_http_log_format &&
6799 curproxy->conf.logformat_string != default_tcp_log_format &&
6800 curproxy->conf.logformat_string != clf_http_log_format)
6801 free(curproxy->conf.logformat_string);
6802 curproxy->conf.logformat_string = NULL;
6803 free(curproxy->conf.lfs_file);
6804 curproxy->conf.lfs_file = NULL;
6805 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006806 }
6807
Willy Tarreau62a61232013-04-12 18:13:46 +02006808 if (curproxy->conf.logformat_string) {
6809 curproxy->conf.args.ctx = ARGC_LOG;
6810 curproxy->conf.args.file = curproxy->conf.lfs_file;
6811 curproxy->conf.args.line = curproxy->conf.lfs_line;
6812 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006813 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006814 curproxy->conf.args.file = NULL;
6815 curproxy->conf.args.line = 0;
6816 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006817
Willy Tarreau62a61232013-04-12 18:13:46 +02006818 if (curproxy->conf.uniqueid_format_string) {
6819 curproxy->conf.args.ctx = ARGC_UIF;
6820 curproxy->conf.args.file = curproxy->conf.uif_file;
6821 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006822 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08006823 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006824 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006825 curproxy->conf.args.file = NULL;
6826 curproxy->conf.args.line = 0;
6827 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006828
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006829 /* only now we can check if some args remain unresolved.
6830 * This must be done after the users and groups resolution.
6831 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006832 cfgerr += smp_resolve_args(curproxy);
6833 if (!cfgerr)
6834 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006835
Willy Tarreau2738a142006-07-08 17:28:09 +02006836 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006837 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006838 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006839 (!curproxy->timeout.connect ||
6840 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006841 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006842 " | While not properly invalid, you will certainly encounter various problems\n"
6843 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006844 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006845 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006846 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006847 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006848
Willy Tarreau1fa31262007-12-03 00:36:16 +01006849 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6850 * We must still support older configurations, so let's find out whether those
6851 * parameters have been set or must be copied from contimeouts.
6852 */
6853 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006854 if (!curproxy->timeout.tarpit ||
6855 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006856 /* tarpit timeout not set. We search in the following order:
6857 * default.tarpit, curr.connect, default.connect.
6858 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006859 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006860 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006861 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006862 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006863 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006864 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006865 }
6866 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006867 (!curproxy->timeout.queue ||
6868 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006869 /* queue timeout not set. We search in the following order:
6870 * default.queue, curr.connect, default.connect.
6871 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006872 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006873 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006874 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006875 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006876 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006877 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006878 }
6879 }
6880
Willy Tarreau1620ec32011-08-06 17:05:02 +02006881 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006882 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6883 curproxy->check_req = (char *)malloc(curproxy->check_len);
6884 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006885 }
6886
Willy Tarreau215663d2014-06-13 18:30:23 +02006887 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6888 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6889 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6890 proxy_type_str(curproxy), curproxy->id);
6891 err_code |= ERR_WARN;
6892 }
6893
Willy Tarreau193b8c62012-11-22 00:17:38 +01006894 /* ensure that cookie capture length is not too large */
6895 if (curproxy->capture_len >= global.tune.cookie_len) {
6896 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6897 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6898 err_code |= ERR_WARN;
6899 curproxy->capture_len = global.tune.cookie_len - 1;
6900 }
6901
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006902 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006903 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006904 curproxy->req_cap_pool = create_pool("ptrcap",
6905 curproxy->nb_req_cap * sizeof(char *),
6906 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006907 }
6908
6909 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006910 curproxy->rsp_cap_pool = create_pool("ptrcap",
6911 curproxy->nb_rsp_cap * sizeof(char *),
6912 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006913 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006914
Willy Tarreaubaaee002006-06-26 02:48:02 +02006915 /* first, we will invert the servers list order */
6916 newsrv = NULL;
6917 while (curproxy->srv) {
6918 struct server *next;
6919
6920 next = curproxy->srv->next;
6921 curproxy->srv->next = newsrv;
6922 newsrv = curproxy->srv;
6923 if (!next)
6924 break;
6925 curproxy->srv = next;
6926 }
6927
Willy Tarreau17edc812014-01-03 12:14:34 +01006928 /* Check that no server name conflicts. This causes trouble in the stats.
6929 * We only emit a warning for the first conflict affecting each server,
6930 * in order to avoid combinatory explosion if all servers have the same
6931 * name. We do that only for servers which do not have an explicit ID,
6932 * because these IDs were made also for distinguishing them and we don't
6933 * want to annoy people who correctly manage them.
6934 */
6935 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6936 struct server *other_srv;
6937
6938 if (newsrv->puid)
6939 continue;
6940
6941 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6942 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6943 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6944 newsrv->conf.file, newsrv->conf.line,
6945 proxy_type_str(curproxy), curproxy->id,
6946 newsrv->id, other_srv->conf.line);
6947 break;
6948 }
6949 }
6950 }
6951
Willy Tarreaudd701652010-05-25 23:03:02 +02006952 /* assign automatic UIDs to servers which don't have one yet */
6953 next_id = 1;
6954 newsrv = curproxy->srv;
6955 while (newsrv != NULL) {
6956 if (!newsrv->puid) {
6957 /* server ID not set, use automatic numbering with first
6958 * spare entry starting with next_svid.
6959 */
6960 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6961 newsrv->conf.id.key = newsrv->puid = next_id;
6962 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6963 }
6964 next_id++;
6965 newsrv = newsrv->next;
6966 }
6967
Willy Tarreau20697042007-11-15 23:26:18 +01006968 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006969 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006970
Willy Tarreau62c3be22012-01-20 13:12:32 +01006971 /*
6972 * If this server supports a maxconn parameter, it needs a dedicated
6973 * tasks to fill the emptied slots when a connection leaves.
6974 * Also, resolve deferred tracking dependency if needed.
6975 */
6976 newsrv = curproxy->srv;
6977 while (newsrv != NULL) {
6978 if (newsrv->minconn > newsrv->maxconn) {
6979 /* Only 'minconn' was specified, or it was higher than or equal
6980 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6981 * this will avoid further useless expensive computations.
6982 */
6983 newsrv->maxconn = newsrv->minconn;
6984 } else if (newsrv->maxconn && !newsrv->minconn) {
6985 /* minconn was not specified, so we set it to maxconn */
6986 newsrv->minconn = newsrv->maxconn;
6987 }
6988
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006989#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006990 if (newsrv->use_ssl || newsrv->check.use_ssl)
6991 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006992#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006993
Willy Tarreau2f075e92013-12-03 11:11:34 +01006994 /* set the check type on the server */
6995 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6996
Willy Tarreau62c3be22012-01-20 13:12:32 +01006997 if (newsrv->trackit) {
6998 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006999 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007000 char *pname, *sname;
7001
7002 pname = newsrv->trackit;
7003 sname = strrchr(pname, '/');
7004
7005 if (sname)
7006 *sname++ = '\0';
7007 else {
7008 sname = pname;
7009 pname = NULL;
7010 }
7011
7012 if (pname) {
7013 px = findproxy(pname, PR_CAP_BE);
7014 if (!px) {
7015 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7016 proxy_type_str(curproxy), curproxy->id,
7017 newsrv->id, pname);
7018 cfgerr++;
7019 goto next_srv;
7020 }
7021 } else
7022 px = curproxy;
7023
7024 srv = findserver(px, sname);
7025 if (!srv) {
7026 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7027 proxy_type_str(curproxy), curproxy->id,
7028 newsrv->id, sname);
7029 cfgerr++;
7030 goto next_srv;
7031 }
7032
Willy Tarreau32091232014-05-16 13:52:00 +02007033 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7034 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7035 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007036 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007037 "tracking as it does not have any check nor agent enabled.\n",
7038 proxy_type_str(curproxy), curproxy->id,
7039 newsrv->id, px->id, srv->id);
7040 cfgerr++;
7041 goto next_srv;
7042 }
7043
7044 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7045
7046 if (loop) {
7047 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7048 "belongs to a tracking chain looping back to %s/%s.\n",
7049 proxy_type_str(curproxy), curproxy->id,
7050 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007051 cfgerr++;
7052 goto next_srv;
7053 }
7054
7055 if (curproxy != px &&
7056 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7057 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7058 "tracking: disable-on-404 option inconsistency.\n",
7059 proxy_type_str(curproxy), curproxy->id,
7060 newsrv->id, px->id, srv->id);
7061 cfgerr++;
7062 goto next_srv;
7063 }
7064
7065 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007066 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007067 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007068 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007069 newsrv->check.health = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09007070 newsrv->agent.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007071 }
7072
7073 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007074 newsrv->tracknext = srv->trackers;
7075 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007076
7077 free(newsrv->trackit);
7078 newsrv->trackit = NULL;
7079 }
7080 next_srv:
7081 newsrv = newsrv->next;
7082 }
7083
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007084 /* We have to initialize the server lookup mechanism depending
7085 * on what LB algorithm was choosen.
7086 */
7087
7088 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7089 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7090 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007091 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7092 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7093 init_server_map(curproxy);
7094 } else {
7095 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7096 fwrr_init_server_groups(curproxy);
7097 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007098 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007099
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007100 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007101 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7102 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7103 fwlc_init_server_tree(curproxy);
7104 } else {
7105 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7106 fas_init_server_tree(curproxy);
7107 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007108 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007109
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007110 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007111 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7112 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7113 chash_init_server_tree(curproxy);
7114 } else {
7115 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7116 init_server_map(curproxy);
7117 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007118 break;
7119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007120
7121 if (curproxy->options & PR_O_LOGASAP)
7122 curproxy->to_log &= ~LW_BYTES;
7123
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007124 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007125 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007126 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7127 proxy_type_str(curproxy), curproxy->id);
7128 err_code |= ERR_WARN;
7129 }
7130
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007131 if (curproxy->mode != PR_MODE_HTTP) {
7132 int optnum;
7133
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007134 if (curproxy->uri_auth) {
7135 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7136 proxy_type_str(curproxy), curproxy->id);
7137 err_code |= ERR_WARN;
7138 curproxy->uri_auth = NULL;
7139 }
7140
Willy Tarreau87cf5142011-08-19 22:57:24 +02007141 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007142 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7143 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7144 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007145 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007146 }
7147
7148 if (curproxy->options & PR_O_ORGTO) {
7149 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7150 "originalto", proxy_type_str(curproxy), curproxy->id);
7151 err_code |= ERR_WARN;
7152 curproxy->options &= ~PR_O_ORGTO;
7153 }
7154
7155 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7156 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7157 (curproxy->cap & cfg_opts[optnum].cap) &&
7158 (curproxy->options & cfg_opts[optnum].val)) {
7159 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7160 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7161 err_code |= ERR_WARN;
7162 curproxy->options &= ~cfg_opts[optnum].val;
7163 }
7164 }
7165
7166 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7167 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7168 (curproxy->cap & cfg_opts2[optnum].cap) &&
7169 (curproxy->options2 & cfg_opts2[optnum].val)) {
7170 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7171 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7172 err_code |= ERR_WARN;
7173 curproxy->options2 &= ~cfg_opts2[optnum].val;
7174 }
7175 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007176
Pieter Baauwd551fb52013-05-08 22:49:23 +02007177#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007178 if (curproxy->conn_src.bind_hdr_occ) {
7179 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007180 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007181 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007182 err_code |= ERR_WARN;
7183 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007185 }
7186
Willy Tarreaubaaee002006-06-26 02:48:02 +02007187 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007188 * ensure that we're not cross-dressing a TCP server into HTTP.
7189 */
7190 newsrv = curproxy->srv;
7191 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007192 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007193 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7194 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007195 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007196 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007197
Willy Tarreau0cec3312011-10-31 13:49:26 +01007198 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7199 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7200 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7201 err_code |= ERR_WARN;
7202 }
7203
Willy Tarreauc93cd162014-05-13 15:54:22 +02007204 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007205 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7206 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7207 err_code |= ERR_WARN;
7208 }
7209
Pieter Baauwd551fb52013-05-08 22:49:23 +02007210#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007211 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7212 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007213 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 +01007214 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007215 err_code |= ERR_WARN;
7216 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007217#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007218 newsrv = newsrv->next;
7219 }
7220
Willy Tarreaue42bd962014-09-16 16:21:19 +02007221 /* check if we have a frontend with "tcp-request content" looking at L7
7222 * with no inspect-delay
7223 */
7224 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7225 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7226 if (trule->action == TCP_ACT_CAPTURE &&
7227 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7228 break;
7229 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7230 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7231 break;
7232 }
7233
7234 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7235 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7236 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7237 " This means that these rules will randomly find their contents. This can be fixed by"
7238 " setting the tcp-request inspect-delay.\n",
7239 proxy_type_str(curproxy), curproxy->id);
7240 err_code |= ERR_WARN;
7241 }
7242 }
7243
Willy Tarreauc1a21672009-08-16 22:37:44 +02007244 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007245 if (!curproxy->accept)
7246 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007247
Willy Tarreauc1a21672009-08-16 22:37:44 +02007248 if (curproxy->tcp_req.inspect_delay ||
7249 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007250 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007251
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007252 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007253 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007254 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007255 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007256
7257 /* both TCP and HTTP must check switching rules */
7258 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7259 }
7260
7261 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007262 if (curproxy->tcp_req.inspect_delay ||
7263 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7264 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7265
Emeric Brun97679e72010-09-23 17:56:44 +02007266 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7267 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7268
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007269 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007270 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007271 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007272 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007273
7274 /* If the backend does requires RDP cookie persistence, we have to
7275 * enable the corresponding analyser.
7276 */
7277 if (curproxy->options2 & PR_O2_RDPC_PRST)
7278 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7279 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007280 }
7281
7282 /***********************************************************/
7283 /* At this point, target names have already been resolved. */
7284 /***********************************************************/
7285
7286 /* Check multi-process mode compatibility */
7287
7288 if (global.nbproc > 1 && global.stats_fe) {
7289 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7290 unsigned long mask;
7291
7292 mask = nbits(global.nbproc);
7293 if (global.stats_fe->bind_proc)
7294 mask &= global.stats_fe->bind_proc;
7295
7296 if (bind_conf->bind_proc)
7297 mask &= bind_conf->bind_proc;
7298
7299 /* stop here if more than one process is used */
7300 if (popcount(mask) > 1)
7301 break;
7302 }
7303 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7304 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");
7305 }
7306 }
7307
7308 /* Make each frontend inherit bind-process from its listeners when not specified. */
7309 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7310 if (curproxy->bind_proc)
7311 continue;
7312
7313 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7314 unsigned long mask;
7315
7316 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7317 curproxy->bind_proc |= mask;
7318 }
7319
7320 if (!curproxy->bind_proc)
7321 curproxy->bind_proc = ~0UL;
7322 }
7323
7324 if (global.stats_fe) {
7325 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7326 unsigned long mask;
7327
7328 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7329 global.stats_fe->bind_proc |= mask;
7330 }
7331 if (!global.stats_fe->bind_proc)
7332 global.stats_fe->bind_proc = ~0UL;
7333 }
7334
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007335 /* propagate bindings from frontends to backends. Don't do it if there
7336 * are any fatal errors as we must not call it with unresolved proxies.
7337 */
7338 if (!cfgerr) {
7339 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7340 if (curproxy->cap & PR_CAP_FE)
7341 propagate_processes(curproxy, NULL);
7342 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007343 }
7344
7345 /* Bind each unbound backend to all processes when not specified. */
7346 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7347 if (curproxy->bind_proc)
7348 continue;
7349 curproxy->bind_proc = ~0UL;
7350 }
7351
7352 /*******************************************************/
7353 /* At this step, all proxies have a non-null bind_proc */
7354 /*******************************************************/
7355
7356 /* perform the final checks before creating tasks */
7357
7358 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7359 struct listener *listener;
7360 unsigned int next_id;
7361 int nbproc;
7362
7363 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007364
Emeric Brunc52962f2012-11-15 18:28:02 +01007365#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007366 /* Configure SSL for each bind line.
7367 * Note: if configuration fails at some point, the ->ctx member
7368 * remains NULL so that listeners can later detach.
7369 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007370 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007371 int alloc_ctx;
7372
Emeric Brunc52962f2012-11-15 18:28:02 +01007373 if (!bind_conf->is_ssl) {
7374 if (bind_conf->default_ctx) {
7375 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7376 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7377 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007378 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007379 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007380 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007381 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007382 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007383 cfgerr++;
7384 continue;
7385 }
7386
Emeric Brun8dc60392014-05-09 13:52:00 +02007387 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007388 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007389 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7390 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");
7391 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007392 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007393 cfgerr++;
7394 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007395 }
7396
Emeric Brunfc0421f2012-09-07 17:30:07 +02007397 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007398 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007399 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007400#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007401
Willy Tarreaue6b98942007-10-29 01:09:36 +01007402 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007403 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007404 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007405 if (!listener->luid) {
7406 /* listener ID not set, use automatic numbering with first
7407 * spare entry starting with next_luid.
7408 */
7409 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7410 listener->conf.id.key = listener->luid = next_id;
7411 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007412 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007413 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007414
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007415 /* enable separate counters */
7416 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7417 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007418 if (!listener->name)
7419 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007420 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007421
Willy Tarreaue6b98942007-10-29 01:09:36 +01007422 if (curproxy->options & PR_O_TCP_NOLING)
7423 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007424 if (!listener->maxconn)
7425 listener->maxconn = curproxy->maxconn;
7426 if (!listener->backlog)
7427 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007428 if (!listener->maxaccept)
7429 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7430
7431 /* we want to have an optimal behaviour on single process mode to
7432 * maximize the work at once, but in multi-process we want to keep
7433 * some fairness between processes, so we target half of the max
7434 * number of events to be balanced over all the processes the proxy
7435 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7436 * used to disable the limit.
7437 */
7438 if (listener->maxaccept > 0) {
7439 if (nbproc > 1)
7440 listener->maxaccept = (listener->maxaccept + 1) / 2;
7441 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7442 }
7443
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007444 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007445 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007446 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007447 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007448
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007449 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7450 listener->options |= LI_O_TCP_RULES;
7451
Willy Tarreaude3041d2010-05-31 10:56:17 +02007452 if (curproxy->mon_mask.s_addr)
7453 listener->options |= LI_O_CHK_MONNET;
7454
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007455 /* smart accept mode is automatic in HTTP mode */
7456 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007457 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007458 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7459 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007460 }
7461
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007462 /* Release unused SSL configs */
7463 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7464 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007465 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007466#ifdef USE_OPENSSL
7467 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007468 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007469 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007470 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007471 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007472#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007473 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007474
Willy Tarreau102df612014-05-07 23:56:38 +02007475 if (nbproc > 1) {
7476 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007477 int count, maxproc = 0;
7478
7479 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7480 count = popcount(bind_conf->bind_proc);
7481 if (count > maxproc)
7482 maxproc = count;
7483 }
7484 /* backends have 0, frontends have 1 or more */
7485 if (maxproc != 1)
7486 Warning("Proxy '%s': in multi-process mode, stats will be"
7487 " limited to process assigned to the current request.\n",
7488 curproxy->id);
7489
Willy Tarreau102df612014-05-07 23:56:38 +02007490 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7491 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7492 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007493 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007494 }
Willy Tarreau102df612014-05-07 23:56:38 +02007495 if (curproxy->appsession_name) {
7496 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7497 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007498 }
Willy Tarreau102df612014-05-07 23:56:38 +02007499 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7500 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7501 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007502 }
7503 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007504
7505 /* create the task associated with the proxy */
7506 curproxy->task = task_new();
7507 if (curproxy->task) {
7508 curproxy->task->context = curproxy;
7509 curproxy->task->process = manage_proxy;
7510 /* no need to queue, it will be done automatically if some
7511 * listener gets limited.
7512 */
7513 curproxy->task->expire = TICK_ETERNITY;
7514 } else {
7515 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7516 curproxy->id);
7517 cfgerr++;
7518 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007519 }
7520
Willy Tarreaufbb78422011-06-05 15:38:35 +02007521 /* automatically compute fullconn if not set. We must not do it in the
7522 * loop above because cross-references are not yet fully resolved.
7523 */
7524 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7525 /* If <fullconn> is not set, let's set it to 10% of the sum of
7526 * the possible incoming frontend's maxconns.
7527 */
7528 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7529 struct proxy *fe;
7530 int total = 0;
7531
7532 /* sum up the number of maxconns of frontends which
7533 * reference this backend at least once or which are
7534 * the same one ('listen').
7535 */
7536 for (fe = proxy; fe; fe = fe->next) {
7537 struct switching_rule *rule;
7538 struct hdr_exp *exp;
7539 int found = 0;
7540
7541 if (!(fe->cap & PR_CAP_FE))
7542 continue;
7543
7544 if (fe == curproxy) /* we're on a "listen" instance */
7545 found = 1;
7546
7547 if (fe->defbe.be == curproxy) /* "default_backend" */
7548 found = 1;
7549
7550 /* check if a "use_backend" rule matches */
7551 if (!found) {
7552 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007553 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007554 found = 1;
7555 break;
7556 }
7557 }
7558 }
7559
7560 /* check if a "reqsetbe" rule matches */
7561 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7562 if (exp->action == ACT_SETBE &&
7563 (struct proxy *)exp->replace == curproxy) {
7564 found = 1;
7565 break;
7566 }
7567 }
7568
7569 /* now we've checked all possible ways to reference a backend
7570 * from a frontend.
7571 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007572 if (!found)
7573 continue;
7574 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007575 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007576 /* we have the sum of the maxconns in <total>. We only
7577 * keep 10% of that sum to set the default fullconn, with
7578 * a hard minimum of 1 (to avoid a divide by zero).
7579 */
7580 curproxy->fullconn = (total + 9) / 10;
7581 if (!curproxy->fullconn)
7582 curproxy->fullconn = 1;
7583 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007584 }
7585
Willy Tarreau056f5682010-06-06 15:51:11 +02007586 /* initialize stick-tables on backend capable proxies. This must not
7587 * be done earlier because the data size may be discovered while parsing
7588 * other proxies.
7589 */
Godbach9703e662013-12-11 21:11:41 +08007590 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007591 if (curproxy->state == PR_STSTOPPED)
7592 continue;
7593
Godbach9703e662013-12-11 21:11:41 +08007594 if (!stktable_init(&curproxy->table)) {
7595 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7596 cfgerr++;
7597 }
7598 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007599
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007600 /*
7601 * Recount currently required checks.
7602 */
7603
7604 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7605 int optnum;
7606
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007607 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7608 if (curproxy->options & cfg_opts[optnum].val)
7609 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007610
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007611 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7612 if (curproxy->options2 & cfg_opts2[optnum].val)
7613 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007614 }
7615
Willy Tarreau122541c2011-09-07 21:24:49 +02007616 if (peers) {
7617 struct peers *curpeers = peers, **last;
7618 struct peer *p, *pb;
7619
7620 /* Remove all peers sections which don't have a valid listener.
7621 * This can happen when a peers section is never referenced and
7622 * does not contain a local peer.
7623 */
7624 last = &peers;
7625 while (*last) {
7626 curpeers = *last;
7627 if (curpeers->peers_fe) {
7628 last = &curpeers->next;
7629 continue;
7630 }
7631
7632 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7633 curpeers->id, localpeer);
7634
7635 p = curpeers->remote;
7636 while (p) {
7637 pb = p->next;
7638 free(p->id);
7639 free(p);
7640 p = pb;
7641 }
7642
7643 /* Destroy and unlink this curpeers section.
7644 * Note: curpeers is backed up into *last.
7645 */
7646 free(curpeers->id);
7647 curpeers = curpeers->next;
7648 free(*last);
7649 *last = curpeers;
7650 }
7651 }
7652
Willy Tarreau34eb6712011-10-24 18:15:04 +02007653 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007654 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007655 MEM_F_SHARED);
7656
Willy Tarreaubb925012009-07-23 13:36:36 +02007657 if (cfgerr > 0)
7658 err_code |= ERR_ALERT | ERR_FATAL;
7659 out:
7660 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007661}
7662
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007663/*
7664 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7665 * parsing sessions.
7666 */
7667void cfg_register_keywords(struct cfg_kw_list *kwl)
7668{
7669 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7670}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007671
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007672/*
7673 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7674 */
7675void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7676{
7677 LIST_DEL(&kwl->list);
7678 LIST_INIT(&kwl->list);
7679}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007680
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007681/* this function register new section in the haproxy configuration file.
7682 * <section_name> is the name of this new section and <section_parser>
7683 * is the called parser. If two section declaration have the same name,
7684 * only the first declared is used.
7685 */
7686int cfg_register_section(char *section_name,
7687 int (*section_parser)(const char *, int, char **, int))
7688{
7689 struct cfg_section *cs;
7690
7691 cs = calloc(1, sizeof(*cs));
7692 if (!cs) {
7693 Alert("register section '%s': out of memory.\n", section_name);
7694 return 0;
7695 }
7696
7697 cs->section_name = section_name;
7698 cs->section_parser = section_parser;
7699
7700 LIST_ADDQ(&sections, &cs->list);
7701
7702 return 1;
7703}
7704
Willy Tarreaubaaee002006-06-26 02:48:02 +02007705/*
7706 * Local variables:
7707 * c-indent-level: 8
7708 * c-basic-offset: 8
7709 * End:
7710 */