blob: fff95e17c278ab50f2308f0ced8e82d60932e4a9 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté2c8d7002014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau1c3a6122015-05-01 15:37:53 +0200154 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
283 ss = *ss2;
284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200543 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 if (!strcmp(args[0], "global")) { /* new section */
546 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200549 else if (!strcmp(args[0], "ca-base")) {
550#ifdef USE_OPENSSL
551 if (global.ca_base != NULL) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.ca_base = strdup(args[1]);
562#else
563 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566#endif
567 }
568 else if (!strcmp(args[0], "crt-base")) {
569#ifdef USE_OPENSSL
570 if (global.crt_base != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT;
573 goto out;
574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.crt_base = strdup(args[1]);
581#else
582 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585#endif
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 else if (!strcmp(args[0], "daemon")) {
588 global.mode |= MODE_DAEMON;
589 }
590 else if (!strcmp(args[0], "debug")) {
591 global.mode |= MODE_DEBUG;
592 }
593 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100594 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200596 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100602 else if (!strcmp(args[0], "nosplice")) {
603 global.tune.options &= ~GTUNE_USE_SPLICE;
604 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605 else if (!strcmp(args[0], "nogetaddrinfo")) {
606 global.tune.options &= ~GTUNE_USE_GAI;
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "quiet")) {
609 global.mode |= MODE_QUIET;
610 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200611 else if (!strcmp(args[0], "tune.maxpollevents")) {
612 if (global.tune.maxpollevents != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200621 }
622 global.tune.maxpollevents = atol(args[1]);
623 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100624 else if (!strcmp(args[0], "tune.maxaccept")) {
625 if (global.tune.maxaccept != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100634 }
635 global.tune.maxaccept = atol(args[1]);
636 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200637 else if (!strcmp(args[0], "tune.chksize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.chksize = atol(args[1]);
644 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200645#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200646 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
647 global.tune.sslprivatecache = 1;
648 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100649 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.sslcachesize = atol(args[1]);
656 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100657 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
658 unsigned int ssllifetime;
659 const char *res;
660
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666
667 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
668 if (res) {
669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
670 file, linenum, *res, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 global.tune.ssllifetime = ssllifetime;
676 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100677 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.ssl_max_record = atol(args[1]);
684 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200685 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.ssl_default_dh_param = atol(args[1]);
692 if (global.tune.ssl_default_dh_param < 1024) {
693 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200698#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200699 else if (!strcmp(args[0], "tune.bufsize")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.bufsize = atol(args[1]);
Willy Tarreau47c7d632015-09-28 13:49:53 +0200706 if (global.tune.bufsize <= 0) {
707 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
708 err_code |= ERR_ALERT | ERR_FATAL;
709 goto out;
710 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200711 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
712 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100713 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100714 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200715 }
716 else if (!strcmp(args[0], "tune.maxrewrite")) {
717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.tune.maxrewrite = atol(args[1]);
723 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
724 global.tune.maxrewrite = global.tune.bufsize / 2;
725 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100726 else if (!strcmp(args[0], "tune.idletimer")) {
727 unsigned int idle;
728 const char *res;
729
730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735
736 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
737 if (res) {
738 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
739 file, linenum, *res, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743
744 if (idle > 65535) {
745 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749 global.tune.idle_timer = idle;
750 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100751 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
752 if (global.tune.client_rcvbuf != 0) {
753 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT;
755 goto out;
756 }
757 if (*(args[1]) == 0) {
758 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
759 err_code |= ERR_ALERT | ERR_FATAL;
760 goto out;
761 }
762 global.tune.client_rcvbuf = atol(args[1]);
763 }
764 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
765 if (global.tune.server_rcvbuf != 0) {
766 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT;
768 goto out;
769 }
770 if (*(args[1]) == 0) {
771 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
772 err_code |= ERR_ALERT | ERR_FATAL;
773 goto out;
774 }
775 global.tune.server_rcvbuf = atol(args[1]);
776 }
777 else if (!strcmp(args[0], "tune.sndbuf.client")) {
778 if (global.tune.client_sndbuf != 0) {
779 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT;
781 goto out;
782 }
783 if (*(args[1]) == 0) {
784 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788 global.tune.client_sndbuf = atol(args[1]);
789 }
790 else if (!strcmp(args[0], "tune.sndbuf.server")) {
791 if (global.tune.server_sndbuf != 0) {
792 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT;
794 goto out;
795 }
796 if (*(args[1]) == 0) {
797 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
798 err_code |= ERR_ALERT | ERR_FATAL;
799 goto out;
800 }
801 global.tune.server_sndbuf = atol(args[1]);
802 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200803 else if (!strcmp(args[0], "tune.pipesize")) {
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.pipesize = atol(args[1]);
810 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100811 else if (!strcmp(args[0], "tune.http.cookielen")) {
812 if (*(args[1]) == 0) {
813 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
814 err_code |= ERR_ALERT | ERR_FATAL;
815 goto out;
816 }
817 global.tune.cookie_len = atol(args[1]) + 1;
818 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200819 else if (!strcmp(args[0], "tune.http.maxhdr")) {
820 if (*(args[1]) == 0) {
821 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
822 err_code |= ERR_ALERT | ERR_FATAL;
823 goto out;
824 }
825 global.tune.max_http_hdr = atol(args[1]);
826 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100827 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
828#ifdef USE_ZLIB
829 if (*args[1]) {
830 global.tune.zlibmemlevel = atoi(args[1]);
831 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
832 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
833 file, linenum, args[0]);
834 err_code |= ERR_ALERT | ERR_FATAL;
835 goto out;
836 }
837 } else {
838 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
839 file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843#else
844 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847#endif
848 }
849 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
850#ifdef USE_ZLIB
851 if (*args[1]) {
852 global.tune.zlibwindowsize = atoi(args[1]);
853 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 } else {
860 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
861 file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865#else
866 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869#endif
870 }
William Lallemandf3747832012-11-09 12:33:10 +0100871 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
872 if (*args[1]) {
873 global.tune.comp_maxlevel = atoi(args[1]);
874 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
875 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
876 file, linenum, args[0]);
877 err_code |= ERR_ALERT | ERR_FATAL;
878 goto out;
879 }
880 } else {
881 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
882 file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 else if (!strcmp(args[0], "uid")) {
888 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200889 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 if (*(args[1]) == 0) {
894 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200895 err_code |= ERR_ALERT | ERR_FATAL;
896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200897 }
Baptiste Assmann2b429932016-03-11 17:10:04 +0100898 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
899 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
900 err_code |= ERR_WARN;
901 goto out;
902 }
903
Willy Tarreaubaaee002006-06-26 02:48:02 +0200904 }
905 else if (!strcmp(args[0], "gid")) {
906 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200907 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200908 err_code |= ERR_ALERT;
909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200910 }
911 if (*(args[1]) == 0) {
912 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200915 }
916 global.gid = atol(args[1]);
917 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200918 /* user/group name handling */
919 else if (!strcmp(args[0], "user")) {
920 struct passwd *ha_user;
921 if (global.uid != 0) {
922 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200923 err_code |= ERR_ALERT;
924 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200925 }
926 errno = 0;
927 ha_user = getpwnam(args[1]);
928 if (ha_user != NULL) {
929 global.uid = (int)ha_user->pw_uid;
930 }
931 else {
932 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 +0200933 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200934 }
935 }
936 else if (!strcmp(args[0], "group")) {
937 struct group *ha_group;
938 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200939 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT;
941 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200942 }
943 errno = 0;
944 ha_group = getgrnam(args[1]);
945 if (ha_group != NULL) {
946 global.gid = (int)ha_group->gr_gid;
947 }
948 else {
949 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 +0200950 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200951 }
952 }
953 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200954 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200955 if (*(args[1]) == 0) {
956 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200957 err_code |= ERR_ALERT | ERR_FATAL;
958 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 }
960 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100961 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
962 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
963 file, linenum, args[0], LONGBITS, global.nbproc);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200967 }
968 else if (!strcmp(args[0], "maxconn")) {
969 if (global.maxconn != 0) {
970 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200971 err_code |= ERR_ALERT;
972 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200973 }
974 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.maxconn = atol(args[1]);
980#ifdef SYSTEM_MAXCONN
981 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
982 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);
983 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200984 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200985 }
986#endif /* SYSTEM_MAXCONN */
987 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200988 else if (!strcmp(args[0], "maxsslconn")) {
989#ifdef USE_OPENSSL
990 if (*(args[1]) == 0) {
991 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995 global.maxsslconn = atol(args[1]);
996#else
Emeric Brun0914df82012-10-02 18:45:42 +0200997 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001000#endif
1001 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001002 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1003#ifdef USE_OPENSSL
1004 if (*(args[1]) == 0) {
1005 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1006 err_code |= ERR_ALERT | ERR_FATAL;
1007 goto out;
1008 }
1009 free(global.listen_default_ciphers);
1010 global.listen_default_ciphers = strdup(args[1]);
1011#else
1012 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1013 err_code |= ERR_ALERT | ERR_FATAL;
1014 goto out;
1015#endif
1016 }
1017 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1018#ifdef USE_OPENSSL
1019 if (*(args[1]) == 0) {
1020 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1021 err_code |= ERR_ALERT | ERR_FATAL;
1022 goto out;
1023 }
1024 free(global.connect_default_ciphers);
1025 global.connect_default_ciphers = strdup(args[1]);
1026#else
1027 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1028 err_code |= ERR_ALERT | ERR_FATAL;
1029 goto out;
1030#endif
1031 }
Emeric Brun850efd52014-01-29 12:24:34 +01001032 else if (!strcmp(args[0], "ssl-server-verify")) {
1033 if (*(args[1]) == 0) {
1034 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037 }
1038 if (strcmp(args[1],"none") == 0)
1039 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1040 else if (strcmp(args[1],"required") == 0)
1041 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1042 else {
1043 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1044 err_code |= ERR_ALERT | ERR_FATAL;
1045 goto out;
1046 }
1047 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001048 else if (!strcmp(args[0], "maxconnrate")) {
1049 if (global.cps_lim != 0) {
1050 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1051 err_code |= ERR_ALERT;
1052 goto out;
1053 }
1054 if (*(args[1]) == 0) {
1055 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1056 err_code |= ERR_ALERT | ERR_FATAL;
1057 goto out;
1058 }
1059 global.cps_lim = atol(args[1]);
1060 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001061 else if (!strcmp(args[0], "maxsessrate")) {
1062 if (global.sps_lim != 0) {
1063 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1064 err_code |= ERR_ALERT;
1065 goto out;
1066 }
1067 if (*(args[1]) == 0) {
1068 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1069 err_code |= ERR_ALERT | ERR_FATAL;
1070 goto out;
1071 }
1072 global.sps_lim = atol(args[1]);
1073 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001074 else if (!strcmp(args[0], "maxsslrate")) {
1075 if (global.ssl_lim != 0) {
1076 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1077 err_code |= ERR_ALERT;
1078 goto out;
1079 }
1080 if (*(args[1]) == 0) {
1081 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1082 err_code |= ERR_ALERT | ERR_FATAL;
1083 goto out;
1084 }
1085 global.ssl_lim = atol(args[1]);
1086 }
William Lallemandd85f9172012-11-09 17:05:39 +01001087 else if (!strcmp(args[0], "maxcomprate")) {
1088 if (*(args[1]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
1092 }
1093 global.comp_rate_lim = atoi(args[1]) * 1024;
1094 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001095 else if (!strcmp(args[0], "maxpipes")) {
1096 if (global.maxpipes != 0) {
1097 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001098 err_code |= ERR_ALERT;
1099 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001100 }
1101 if (*(args[1]) == 0) {
1102 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001103 err_code |= ERR_ALERT | ERR_FATAL;
1104 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001105 }
1106 global.maxpipes = atol(args[1]);
1107 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001108 else if (!strcmp(args[0], "maxzlibmem")) {
1109 if (*(args[1]) == 0) {
1110 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1111 err_code |= ERR_ALERT | ERR_FATAL;
1112 goto out;
1113 }
William Lallemande3a7d992012-11-20 11:25:20 +01001114 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001115 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001116 else if (!strcmp(args[0], "maxcompcpuusage")) {
1117 if (*(args[1]) == 0) {
1118 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1119 err_code |= ERR_ALERT | ERR_FATAL;
1120 goto out;
1121 }
1122 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001123 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001124 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
1127 }
1128}
1129
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 else if (!strcmp(args[0], "ulimit-n")) {
1131 if (global.rlimit_nofile != 0) {
1132 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001133 err_code |= ERR_ALERT;
1134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 if (*(args[1]) == 0) {
1137 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001138 err_code |= ERR_ALERT | ERR_FATAL;
1139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 }
1141 global.rlimit_nofile = atol(args[1]);
1142 }
1143 else if (!strcmp(args[0], "chroot")) {
1144 if (global.chroot != NULL) {
1145 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001146 err_code |= ERR_ALERT;
1147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148 }
1149 if (*(args[1]) == 0) {
1150 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001151 err_code |= ERR_ALERT | ERR_FATAL;
1152 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001153 }
1154 global.chroot = strdup(args[1]);
1155 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001156 else if (!strcmp(args[0], "description")) {
1157 int i, len=0;
1158 char *d;
1159
1160 if (!*args[1]) {
1161 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1162 file, linenum, args[0]);
1163 err_code |= ERR_ALERT | ERR_FATAL;
1164 goto out;
1165 }
1166
Willy Tarreau348acfe2014-04-14 15:00:39 +02001167 for (i = 1; *args[i]; i++)
1168 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001169
1170 if (global.desc)
1171 free(global.desc);
1172
1173 global.desc = d = (char *)calloc(1, len);
1174
Willy Tarreau348acfe2014-04-14 15:00:39 +02001175 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1176 for (i = 2; *args[i]; i++)
1177 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001178 }
1179 else if (!strcmp(args[0], "node")) {
1180 int i;
1181 char c;
1182
1183 for (i=0; args[1][i]; i++) {
1184 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001185 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1186 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001187 break;
1188 }
1189
1190 if (!i || args[1][i]) {
1191 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1192 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1193 file, linenum, args[0]);
1194 err_code |= ERR_ALERT | ERR_FATAL;
1195 goto out;
1196 }
1197
1198 if (global.node)
1199 free(global.node);
1200
1201 global.node = strdup(args[1]);
1202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 else if (!strcmp(args[0], "pidfile")) {
1204 if (global.pidfile != NULL) {
1205 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT;
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 }
1209 if (*(args[1]) == 0) {
1210 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001211 err_code |= ERR_ALERT | ERR_FATAL;
1212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001213 }
1214 global.pidfile = strdup(args[1]);
1215 }
Emeric Bruned760922010-10-22 17:59:25 +02001216 else if (!strcmp(args[0], "unix-bind")) {
1217 int cur_arg = 1;
1218 while (*(args[cur_arg])) {
1219 if (!strcmp(args[cur_arg], "prefix")) {
1220 if (global.unix_bind.prefix != NULL) {
1221 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1222 err_code |= ERR_ALERT;
1223 cur_arg += 2;
1224 continue;
1225 }
1226
1227 if (*(args[cur_arg+1]) == 0) {
1228 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1229 err_code |= ERR_ALERT | ERR_FATAL;
1230 goto out;
1231 }
1232 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1233 cur_arg += 2;
1234 continue;
1235 }
1236
1237 if (!strcmp(args[cur_arg], "mode")) {
1238
1239 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1240 cur_arg += 2;
1241 continue;
1242 }
1243
1244 if (!strcmp(args[cur_arg], "uid")) {
1245
1246 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1247 cur_arg += 2;
1248 continue;
1249 }
1250
1251 if (!strcmp(args[cur_arg], "gid")) {
1252
1253 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1254 cur_arg += 2;
1255 continue;
1256 }
1257
1258 if (!strcmp(args[cur_arg], "user")) {
1259 struct passwd *user;
1260
1261 user = getpwnam(args[cur_arg + 1]);
1262 if (!user) {
1263 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1264 file, linenum, args[0], args[cur_arg + 1 ]);
1265 err_code |= ERR_ALERT | ERR_FATAL;
1266 goto out;
1267 }
1268
1269 global.unix_bind.ux.uid = user->pw_uid;
1270 cur_arg += 2;
1271 continue;
1272 }
1273
1274 if (!strcmp(args[cur_arg], "group")) {
1275 struct group *group;
1276
1277 group = getgrnam(args[cur_arg + 1]);
1278 if (!group) {
1279 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1280 file, linenum, args[0], args[cur_arg + 1 ]);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284
1285 global.unix_bind.ux.gid = group->gr_gid;
1286 cur_arg += 2;
1287 continue;
1288 }
1289
Willy Tarreaub48f9582011-09-05 01:17:06 +02001290 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001291 file, linenum, args[0]);
1292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
1295 }
William Lallemand0f99e342011-10-12 17:50:54 +02001296 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1297 /* delete previous herited or defined syslog servers */
1298 struct logsrv *back;
1299 struct logsrv *tmp;
1300
1301 if (*(args[1]) != 0) {
1302 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1303 err_code |= ERR_ALERT | ERR_FATAL;
1304 goto out;
1305 }
1306
1307 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1308 LIST_DEL(&tmp->list);
1309 free(tmp);
1310 }
1311 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001312 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001313 struct sockaddr_storage *sk;
1314 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001315 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001316 int arg = 0;
1317 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001318
Willy Tarreaubaaee002006-06-26 02:48:02 +02001319 if (*(args[1]) == 0 || *(args[2]) == 0) {
1320 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 }
William Lallemand0f99e342011-10-12 17:50:54 +02001324
1325 logsrv = calloc(1, sizeof(struct logsrv));
1326
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001327 /* just after the address, a length may be specified */
1328 if (strcmp(args[arg+2], "len") == 0) {
1329 len = atoi(args[arg+3]);
1330 if (len < 80 || len > 65535) {
1331 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1332 file, linenum, args[arg+3]);
1333 err_code |= ERR_ALERT | ERR_FATAL;
1334 goto out;
1335 }
1336 logsrv->maxlen = len;
1337
1338 /* skip these two args */
1339 arg += 2;
1340 }
1341 else
1342 logsrv->maxlen = MAX_SYSLOG_LEN;
1343
1344 if (logsrv->maxlen > global.max_syslog_len) {
1345 global.max_syslog_len = logsrv->maxlen;
1346 logline = realloc(logline, global.max_syslog_len + 1);
1347 }
1348
1349 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001350 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001351 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001352 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001353 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001354 }
1355
William Lallemand0f99e342011-10-12 17:50:54 +02001356 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001357 if (*(args[arg+3])) {
1358 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001359 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001360 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001361 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001362 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001363 }
1364 }
1365
William Lallemand0f99e342011-10-12 17:50:54 +02001366 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001367 if (*(args[arg+4])) {
1368 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001369 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001370 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001371 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001372 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001373 }
1374 }
1375
Willy Tarreau902636f2013-03-10 19:44:48 +01001376 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001377 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001378 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001379 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001380 free(logsrv);
1381 goto out;
1382 }
1383 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001384
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001385 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001386 if (port1 != port2) {
1387 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1388 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001389 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001390 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001391 goto out;
1392 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001393
William Lallemand0f99e342011-10-12 17:50:54 +02001394 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001395 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001396 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001397 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398
William Lallemand0f99e342011-10-12 17:50:54 +02001399 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001400 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001401 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1402 char *name;
1403 int len;
1404
1405 if (global.log_send_hostname != NULL) {
1406 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1407 err_code |= ERR_ALERT;
1408 goto out;
1409 }
1410
1411 if (*(args[1]))
1412 name = args[1];
1413 else
1414 name = hostname;
1415
1416 len = strlen(name);
1417
1418 /* We'll add a space after the name to respect the log format */
1419 free(global.log_send_hostname);
1420 global.log_send_hostname = malloc(len + 2);
1421 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1422 }
Kevinm48936af2010-12-22 16:08:21 +00001423 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1424 if (*(args[1]) == 0) {
1425 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1426 err_code |= ERR_ALERT | ERR_FATAL;
1427 goto out;
1428 }
1429 free(global.log_tag);
1430 global.log_tag = strdup(args[1]);
1431 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001432 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1433 if (global.spread_checks != 0) {
1434 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001435 err_code |= ERR_ALERT;
1436 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001437 }
1438 if (*(args[1]) == 0) {
1439 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001440 err_code |= ERR_ALERT | ERR_FATAL;
1441 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001442 }
1443 global.spread_checks = atol(args[1]);
1444 if (global.spread_checks < 0 || global.spread_checks > 50) {
1445 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001446 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001448 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001449 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1450 const char *err;
1451 unsigned int val;
1452
1453
1454 if (*(args[1]) == 0) {
1455 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1456 err_code |= ERR_ALERT | ERR_FATAL;
1457 goto out;
1458 }
1459
1460 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1461 if (err) {
1462 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1463 err_code |= ERR_ALERT | ERR_FATAL;
1464 }
1465 global.max_spread_checks = val;
1466 if (global.max_spread_checks < 0) {
1467 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1468 err_code |= ERR_ALERT | ERR_FATAL;
1469 }
1470 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001471 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1472#ifdef USE_CPU_AFFINITY
1473 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001474 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001475 unsigned long cpus = 0;
1476
1477 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001478 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001479 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001480 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001481 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001482 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001483 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001484 proc = atol(args[1]);
1485 if (proc >= 1 && proc <= LONGBITS)
1486 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001487 }
1488
1489 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001490 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",
1491 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001492 err_code |= ERR_ALERT | ERR_FATAL;
1493 goto out;
1494 }
1495
1496 cur_arg = 2;
1497 while (*args[cur_arg]) {
1498 unsigned int low, high;
1499
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001500 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001501 char *dash = strchr(args[cur_arg], '-');
1502
1503 low = high = str2uic(args[cur_arg]);
1504 if (dash)
1505 high = str2uic(dash + 1);
1506
1507 if (high < low) {
1508 unsigned int swap = low;
1509 low = high;
1510 high = swap;
1511 }
1512
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001513 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001514 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001515 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
1518 }
1519
1520 while (low <= high)
1521 cpus |= 1UL << low++;
1522 }
1523 else {
1524 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1525 file, linenum, args[0], args[cur_arg]);
1526 err_code |= ERR_ALERT | ERR_FATAL;
1527 goto out;
1528 }
1529 cur_arg++;
1530 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001531 for (i = 0; i < LONGBITS; i++)
1532 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001533 global.cpu_map[i] = cpus;
1534#else
1535 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538#endif
1539 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001541 struct cfg_kw_list *kwl;
1542 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001543 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001544
1545 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1546 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1547 if (kwl->kw[index].section != CFG_GLOBAL)
1548 continue;
1549 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001550 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001551 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001552 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001553 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001554 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001555 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001556 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001557 err_code |= ERR_WARN;
1558 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001559 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001560 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001561 }
1562 }
1563 }
1564
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001566 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001568
Willy Tarreau058e9072009-07-20 09:30:05 +02001569 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001570 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001571 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572}
1573
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001574void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001575{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001576 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 defproxy.mode = PR_MODE_TCP;
1578 defproxy.state = PR_STNEW;
1579 defproxy.maxconn = cfg_maxpconn;
1580 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001581
Simon Horman66183002013-02-23 10:16:43 +09001582 defproxy.defsrv.check.inter = DEF_CHKINTR;
1583 defproxy.defsrv.check.fastinter = 0;
1584 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001585 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1586 defproxy.defsrv.agent.fastinter = 0;
1587 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001588 defproxy.defsrv.check.rise = DEF_RISETIME;
1589 defproxy.defsrv.check.fall = DEF_FALLTIME;
1590 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1591 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001592 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001593 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001594 defproxy.defsrv.maxqueue = 0;
1595 defproxy.defsrv.minconn = 0;
1596 defproxy.defsrv.maxconn = 0;
1597 defproxy.defsrv.slowstart = 0;
1598 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1599 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1600 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001601}
1602
Willy Tarreauade5ec42010-01-28 19:33:49 +01001603
Willy Tarreau63af98d2014-05-18 08:11:41 +02001604/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1605 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1606 * ERR_FATAL in case of error.
1607 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001608static int create_cond_regex_rule(const char *file, int line,
1609 struct proxy *px, int dir, int action, int flags,
1610 const char *cmd, const char *reg, const char *repl,
1611 const char **cond_start)
1612{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001613 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001614 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001615 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001616 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001617 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001618 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001619 int cs;
1620 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001621
1622 if (px == &defproxy) {
1623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001624 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001625 goto err;
1626 }
1627
1628 if (*reg == 0) {
1629 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001630 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001631 goto err;
1632 }
1633
1634 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001635 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001636
Willy Tarreau5321c422010-01-28 20:35:13 +01001637 if (cond_start &&
1638 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001639 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1640 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1641 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001642 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001643 goto err;
1644 }
1645 }
1646 else if (cond_start && **cond_start) {
1647 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1648 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001649 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001650 goto err;
1651 }
1652
Willy Tarreau63af98d2014-05-18 08:11:41 +02001653 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001654 (dir == SMP_OPT_DIR_REQ) ?
1655 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1656 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1657 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001658
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001659 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001660 if (!preg) {
1661 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001662 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001663 goto err;
1664 }
1665
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001666 cs = !(flags & REG_ICASE);
1667 cap = !(flags & REG_NOSUB);
1668 error = NULL;
1669 if (!regex_comp(reg, preg, cs, cap, &error)) {
1670 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1671 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001672 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001673 goto err;
1674 }
1675
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001676 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001677 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001678 if (repl && err) {
1679 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1680 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001681 ret_code |= ERR_ALERT | ERR_FATAL;
1682 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001683 }
1684
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001685 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001686 ret_code |= ERR_WARN;
1687
1688 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001689
Willy Tarreau63af98d2014-05-18 08:11:41 +02001690 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001691 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001692 err:
1693 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001694 free(errmsg);
1695 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001696}
1697
Willy Tarreaubaaee002006-06-26 02:48:02 +02001698/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001699 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001700 * Returns the error code, 0 if OK, or any combination of :
1701 * - ERR_ABORT: must abort ASAP
1702 * - ERR_FATAL: we can continue parsing but not start the service
1703 * - ERR_WARN: a warning has been emitted
1704 * - ERR_ALERT: an alert has been emitted
1705 * Only the two first ones can stop processing, the two others are just
1706 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001707 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001708int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1709{
1710 static struct peers *curpeers = NULL;
1711 struct peer *newpeer = NULL;
1712 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001713 struct bind_conf *bind_conf;
1714 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001715 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001716 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001717
1718 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001719 if (!*args[1]) {
1720 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001721 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001722 goto out;
1723 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001724
1725 err = invalid_char(args[1]);
1726 if (err) {
1727 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1728 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001729 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001730 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001731 }
1732
1733 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1734 /*
1735 * If there are two proxies with the same name only following
1736 * combinations are allowed:
1737 */
1738 if (strcmp(curpeers->id, args[1]) == 0) {
1739 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1740 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1741 err_code |= ERR_WARN;
1742 }
1743 }
1744
1745 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1746 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1747 err_code |= ERR_ALERT | ERR_ABORT;
1748 goto out;
1749 }
1750
1751 curpeers->next = peers;
1752 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001753 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001754 curpeers->conf.line = linenum;
1755 curpeers->last_change = now.tv_sec;
1756 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001757 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001758 }
1759 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001760 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001761 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001762 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001763
1764 if (!*args[2]) {
1765 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1766 file, linenum, args[0]);
1767 err_code |= ERR_ALERT | ERR_FATAL;
1768 goto out;
1769 }
1770
1771 err = invalid_char(args[1]);
1772 if (err) {
1773 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1774 file, linenum, *err, args[1]);
1775 err_code |= ERR_ALERT | ERR_FATAL;
1776 goto out;
1777 }
1778
1779 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1780 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1781 err_code |= ERR_ALERT | ERR_ABORT;
1782 goto out;
1783 }
1784
1785 /* the peers are linked backwards first */
1786 curpeers->count++;
1787 newpeer->next = curpeers->remote;
1788 curpeers->remote = newpeer;
1789 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001790 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001791 newpeer->conf.line = linenum;
1792
1793 newpeer->last_change = now.tv_sec;
1794 newpeer->id = strdup(args[1]);
1795
Willy Tarreau902636f2013-03-10 19:44:48 +01001796 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001797 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001798 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001799 err_code |= ERR_ALERT | ERR_FATAL;
1800 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001801 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001802
1803 proto = protocol_by_family(sk->ss_family);
1804 if (!proto || !proto->connect) {
1805 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1806 file, linenum, args[0], args[1]);
1807 err_code |= ERR_ALERT | ERR_FATAL;
1808 goto out;
1809 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001810
1811 if (port1 != port2) {
1812 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1813 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001814 err_code |= ERR_ALERT | ERR_FATAL;
1815 goto out;
1816 }
1817
Willy Tarreau2aa38802013-02-20 19:20:59 +01001818 if (!port1) {
1819 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1820 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001821 err_code |= ERR_ALERT | ERR_FATAL;
1822 goto out;
1823 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001824
Emeric Brun32da3c42010-09-23 18:39:19 +02001825 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001826 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001827 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001828 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001829
Emeric Brun32da3c42010-09-23 18:39:19 +02001830 if (strcmp(newpeer->id, localpeer) == 0) {
1831 /* Current is local peer, it define a frontend */
1832 newpeer->local = 1;
1833
1834 if (!curpeers->peers_fe) {
1835 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1836 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1837 err_code |= ERR_ALERT | ERR_ABORT;
1838 goto out;
1839 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001840
Willy Tarreau237250c2011-07-29 01:49:03 +02001841 init_new_proxy(curpeers->peers_fe);
1842 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001843
1844 curpeers->peers_fe->last_change = now.tv_sec;
1845 curpeers->peers_fe->id = strdup(args[1]);
1846 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001847 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001848 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001849 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001850 curpeers->peers_fe->accept = peer_accept;
1851 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001852 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1853 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreaucdb5e922015-05-01 19:12:05 +02001854 curpeers->peers_fe->bind_proc = 0; /* will be filled by users */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001855
1856 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1857
Willy Tarreau902636f2013-03-10 19:44:48 +01001858 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1859 if (errmsg && *errmsg) {
1860 indent_msg(&errmsg, 2);
1861 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001862 }
1863 else
1864 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1865 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001866 err_code |= ERR_FATAL;
1867 goto out;
1868 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001869
1870 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001871 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001872 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1873 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1874 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1875 l->accept = session_accept;
1876 l->handler = process_session;
1877 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1878 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1879 global.maxsock += l->maxconn;
1880 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001881 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001882 else {
1883 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1884 file, linenum, args[0], args[1],
1885 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1886 err_code |= ERR_FATAL;
1887 goto out;
1888 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001889 }
1890 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001891 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1892 curpeers->state = PR_STSTOPPED;
1893 }
1894 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1895 curpeers->state = PR_STNEW;
1896 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001897 else if (*args[0] != 0) {
1898 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1899 err_code |= ERR_ALERT | ERR_FATAL;
1900 goto out;
1901 }
1902
1903out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001904 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001905 return err_code;
1906}
1907
Willy Tarreau3842f002009-06-14 11:39:52 +02001908int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001909{
1910 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001911 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001912 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001913 int rc;
1914 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001915 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001916 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001917 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001918 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001919 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001920
Willy Tarreau977b8e42006-12-29 14:19:17 +01001921 if (!strcmp(args[0], "listen"))
1922 rc = PR_CAP_LISTEN;
1923 else if (!strcmp(args[0], "frontend"))
1924 rc = PR_CAP_FE | PR_CAP_RS;
1925 else if (!strcmp(args[0], "backend"))
1926 rc = PR_CAP_BE | PR_CAP_RS;
1927 else if (!strcmp(args[0], "ruleset"))
1928 rc = PR_CAP_RS;
1929 else
1930 rc = PR_CAP_NONE;
1931
1932 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001933 struct ebpt_node *node;
1934
Willy Tarreaubaaee002006-06-26 02:48:02 +02001935 if (!*args[1]) {
1936 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1937 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001939 err_code |= ERR_ALERT | ERR_ABORT;
1940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001941 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001942
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001943 err = invalid_char(args[1]);
1944 if (err) {
1945 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1946 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001947 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001948 }
1949
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001950 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1951 curproxy = container_of(node, struct proxy, conf.by_name);
1952
1953 if (strcmp(curproxy->id, args[1]) != 0)
1954 break;
1955
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001956 /*
1957 * If there are two proxies with the same name only following
1958 * combinations are allowed:
1959 *
1960 * listen backend frontend ruleset
1961 * listen - - - -
1962 * backend - - OK -
1963 * frontend - OK - -
1964 * ruleset - - - -
1965 */
1966
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001967 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1968 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001969 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1970 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1971 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001972 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001973 }
1974 }
1975
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1977 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001978 err_code |= ERR_ALERT | ERR_ABORT;
1979 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001981
Willy Tarreau97cb7802010-01-03 20:23:58 +01001982 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001983 curproxy->next = proxy;
1984 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001985 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1986 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001987 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001988 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001989 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001990 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001991
1992 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001993 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001994 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001995
Willy Tarreau4348fad2012-09-20 16:48:07 +02001996 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1997
Willy Tarreau902636f2013-03-10 19:44:48 +01001998 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1999 if (errmsg && *errmsg) {
2000 indent_msg(&errmsg, 2);
2001 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002002 }
2003 else
2004 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2005 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002006 err_code |= ERR_FATAL;
2007 goto out;
2008 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002009
Willy Tarreau4348fad2012-09-20 16:48:07 +02002010 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002011 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002013 }
2014
2015 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002016 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002017 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002018
Willy Tarreaubaaee002006-06-26 02:48:02 +02002019 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002020 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002021 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002022 curproxy->no_options = defproxy.no_options;
2023 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002024 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002025 curproxy->except_net = defproxy.except_net;
2026 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002027 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002028 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002029
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002030 if (defproxy.fwdfor_hdr_len) {
2031 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2032 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2033 }
2034
Willy Tarreaub86db342009-11-30 11:50:16 +01002035 if (defproxy.orgto_hdr_len) {
2036 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2037 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2038 }
2039
Mark Lamourinec2247f02012-01-04 13:02:01 -05002040 if (defproxy.server_id_hdr_len) {
2041 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2042 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2043 }
2044
Willy Tarreau977b8e42006-12-29 14:19:17 +01002045 if (curproxy->cap & PR_CAP_FE) {
2046 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002047 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002048 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049
2050 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002051 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2052 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002053
2054 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2055 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002056
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002058 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002059 curproxy->fullconn = defproxy.fullconn;
2060 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002061 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002062
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002063 if (defproxy.check_req) {
2064 curproxy->check_req = calloc(1, defproxy.check_len);
2065 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2066 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002067 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002068
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002069 if (defproxy.expect_str) {
2070 curproxy->expect_str = strdup(defproxy.expect_str);
2071 if (defproxy.expect_regex) {
2072 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002073 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2074 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002075 }
2076 }
2077
Willy Tarreau67402132012-05-31 20:40:20 +02002078 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 if (defproxy.cookie_name)
2080 curproxy->cookie_name = strdup(defproxy.cookie_name);
2081 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002082 if (defproxy.cookie_domain)
2083 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002084
Willy Tarreau31936852010-10-06 16:59:56 +02002085 if (defproxy.cookie_maxidle)
2086 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2087
2088 if (defproxy.cookie_maxlife)
2089 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2090
Emeric Brun647caf12009-06-30 17:57:00 +02002091 if (defproxy.rdp_cookie_name)
2092 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2093 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2094
Willy Tarreau01732802007-11-01 22:48:15 +01002095 if (defproxy.url_param_name)
2096 curproxy->url_param_name = strdup(defproxy.url_param_name);
2097 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002098
Benoitaffb4812009-03-25 13:02:10 +01002099 if (defproxy.hh_name)
2100 curproxy->hh_name = strdup(defproxy.hh_name);
2101 curproxy->hh_len = defproxy.hh_len;
2102 curproxy->hh_match_domain = defproxy.hh_match_domain;
2103
Willy Tarreauef9a3602012-12-08 22:29:20 +01002104 if (defproxy.conn_src.iface_name)
2105 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2106 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002107 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002108#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002109 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002110#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002111 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002112
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002113 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002114 if (defproxy.capture_name)
2115 curproxy->capture_name = strdup(defproxy.capture_name);
2116 curproxy->capture_namelen = defproxy.capture_namelen;
2117 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002118 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002119
Willy Tarreau977b8e42006-12-29 14:19:17 +01002120 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002121 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002122 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002123 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002124 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002125 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002126 curproxy->mon_net = defproxy.mon_net;
2127 curproxy->mon_mask = defproxy.mon_mask;
2128 if (defproxy.monitor_uri)
2129 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2130 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002131 if (defproxy.defbe.name)
2132 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002133
2134 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002135 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2136 if (curproxy->conf.logformat_string &&
2137 curproxy->conf.logformat_string != default_http_log_format &&
2138 curproxy->conf.logformat_string != default_tcp_log_format &&
2139 curproxy->conf.logformat_string != clf_http_log_format)
2140 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2141
2142 if (defproxy.conf.lfs_file) {
2143 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2144 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2145 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002146 }
2147
2148 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002149 curproxy->timeout.connect = defproxy.timeout.connect;
2150 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002151 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002152 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002153 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002154 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002155 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002156 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002157 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002158 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002159 }
2160
Willy Tarreaubaaee002006-06-26 02:48:02 +02002161 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002162 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002163
2164 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002165 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002166 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002167 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002168 LIST_INIT(&node->list);
2169 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2170 }
2171
Willy Tarreau62a61232013-04-12 18:13:46 +02002172 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2173 if (curproxy->conf.uniqueid_format_string)
2174 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2175
2176 if (defproxy.conf.uif_file) {
2177 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2178 curproxy->conf.uif_line = defproxy.conf.uif_line;
2179 }
William Lallemanda73203e2012-03-12 12:48:57 +01002180
2181 /* copy default header unique id */
2182 if (defproxy.header_unique_id)
2183 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2184
William Lallemand82fe75c2012-10-23 10:25:10 +02002185 /* default compression options */
2186 if (defproxy.comp != NULL) {
2187 curproxy->comp = calloc(1, sizeof(struct comp));
2188 curproxy->comp->algos = defproxy.comp->algos;
2189 curproxy->comp->types = defproxy.comp->types;
2190 }
2191
Willy Tarreaubaaee002006-06-26 02:48:02 +02002192 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002193 curproxy->conf.used_listener_id = EB_ROOT;
2194 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002195
Willy Tarreau93893792009-07-23 13:19:11 +02002196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002197 }
2198 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2199 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002200 /* FIXME-20070101: we should do this too at the end of the
2201 * config parsing to free all default values.
2202 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002203 free(defproxy.check_req);
2204 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002205 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002206 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002207 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002208 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002209 free(defproxy.capture_name);
2210 free(defproxy.monitor_uri);
2211 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002212 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002213 free(defproxy.fwdfor_hdr_name);
2214 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002215 free(defproxy.orgto_hdr_name);
2216 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002217 free(defproxy.server_id_hdr_name);
2218 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002219 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002220 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002221 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002222 free(defproxy.expect_regex);
2223 defproxy.expect_regex = NULL;
2224 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002225
Willy Tarreau62a61232013-04-12 18:13:46 +02002226 if (defproxy.conf.logformat_string != default_http_log_format &&
2227 defproxy.conf.logformat_string != default_tcp_log_format &&
2228 defproxy.conf.logformat_string != clf_http_log_format)
2229 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002230
Willy Tarreau62a61232013-04-12 18:13:46 +02002231 free(defproxy.conf.uniqueid_format_string);
2232 free(defproxy.conf.lfs_file);
2233 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002234
Willy Tarreaua534fea2008-08-03 12:19:50 +02002235 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002236 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002237
Willy Tarreaubaaee002006-06-26 02:48:02 +02002238 /* we cannot free uri_auth because it might already be used */
2239 init_default_instance();
2240 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002241 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2242 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002243 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002245 }
2246 else if (curproxy == NULL) {
2247 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002250 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002251
2252 /* update the current file and line being parsed */
2253 curproxy->conf.args.file = curproxy->conf.file;
2254 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002255
2256 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002257 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2258 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2259 if (err_code & ERR_FATAL)
2260 goto out;
2261 }
2262 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002263 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002264 int cur_arg;
2265
Willy Tarreaubaaee002006-06-26 02:48:02 +02002266 if (curproxy == &defproxy) {
2267 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002268 err_code |= ERR_ALERT | ERR_FATAL;
2269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002271 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002273
Willy Tarreau24709282013-03-10 21:32:12 +01002274 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002275 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002279 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002280
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002281 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002282
2283 /* use default settings for unix sockets */
2284 bind_conf->ux.uid = global.unix_bind.ux.uid;
2285 bind_conf->ux.gid = global.unix_bind.ux.gid;
2286 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002287
2288 /* NOTE: the following line might create several listeners if there
2289 * are comma-separated IPs or port ranges. So all further processing
2290 * will have to be applied to all listeners created after last_listen.
2291 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002292 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2293 if (errmsg && *errmsg) {
2294 indent_msg(&errmsg, 2);
2295 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002296 }
2297 else
2298 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2299 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002300 err_code |= ERR_ALERT | ERR_FATAL;
2301 goto out;
2302 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002303
Willy Tarreau4348fad2012-09-20 16:48:07 +02002304 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2305 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002306 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002307 }
2308
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002309 cur_arg = 2;
2310 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002311 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002312 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002313 char *err;
2314
Willy Tarreau26982662012-09-12 23:17:10 +02002315 kw = bind_find_kw(args[cur_arg]);
2316 if (kw) {
2317 char *err = NULL;
2318 int code;
2319
2320 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002321 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2322 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002323 cur_arg += 1 + kw->skip ;
2324 err_code |= ERR_ALERT | ERR_FATAL;
2325 goto out;
2326 }
2327
Willy Tarreau4348fad2012-09-20 16:48:07 +02002328 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002329 err_code |= code;
2330
2331 if (code) {
2332 if (err && *err) {
2333 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002334 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002335 }
2336 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002337 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2338 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002339 if (code & ERR_FATAL) {
2340 free(err);
2341 cur_arg += 1 + kw->skip;
2342 goto out;
2343 }
2344 }
2345 free(err);
2346 cur_arg += 1 + kw->skip;
2347 continue;
2348 }
2349
Willy Tarreau8638f482012-09-18 18:01:17 +02002350 err = NULL;
2351 if (!bind_dumped) {
2352 bind_dump_kws(&err);
2353 indent_msg(&err, 4);
2354 bind_dumped = 1;
2355 }
2356
2357 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2358 file, linenum, args[0], args[1], args[cur_arg],
2359 err ? " Registered keywords :" : "", err ? err : "");
2360 free(err);
2361
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
2363 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002364 }
Willy Tarreau93893792009-07-23 13:19:11 +02002365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002366 }
2367 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002368 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002369 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002371 err_code |= ERR_ALERT | ERR_FATAL;
2372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002374 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002376
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 /* flush useless bits */
2378 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002381 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002382 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002383 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002384
Willy Tarreau1c47f852006-07-09 08:22:27 +02002385 if (!*args[1]) {
2386 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2387 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002390 }
2391
Willy Tarreaua534fea2008-08-03 12:19:50 +02002392 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002393 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002394 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002395 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002396 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2397
Willy Tarreau93893792009-07-23 13:19:11 +02002398 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002399 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2401 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2402 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2403 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2404 else {
2405 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002406 err_code |= ERR_ALERT | ERR_FATAL;
2407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002408 }
2409 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002410 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002411 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002412
2413 if (curproxy == &defproxy) {
2414 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2415 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002416 err_code |= ERR_ALERT | ERR_FATAL;
2417 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002418 }
2419
2420 if (!*args[1]) {
2421 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2422 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002425 }
2426
2427 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002428 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002429
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002430 if (curproxy->uuid <= 0) {
2431 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002433 err_code |= ERR_ALERT | ERR_FATAL;
2434 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002435 }
2436
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002437 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2438 if (node) {
2439 struct proxy *target = container_of(node, struct proxy, conf.id);
2440 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2441 file, linenum, proxy_type_str(curproxy), curproxy->id,
2442 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2443 err_code |= ERR_ALERT | ERR_FATAL;
2444 goto out;
2445 }
2446 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002447 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002448 else if (!strcmp(args[0], "description")) {
2449 int i, len=0;
2450 char *d;
2451
Cyril Bonté99ed3272010-01-24 23:29:44 +01002452 if (curproxy == &defproxy) {
2453 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2454 file, linenum, args[0]);
2455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
2457 }
2458
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002459 if (!*args[1]) {
2460 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2461 file, linenum, args[0]);
2462 return -1;
2463 }
2464
Willy Tarreau348acfe2014-04-14 15:00:39 +02002465 for (i = 1; *args[i]; i++)
2466 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002467
2468 d = (char *)calloc(1, len);
2469 curproxy->desc = d;
2470
Willy Tarreau348acfe2014-04-14 15:00:39 +02002471 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2472 for (i = 2; *args[i]; i++)
2473 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002474
2475 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002476 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2477 curproxy->state = PR_STSTOPPED;
2478 }
2479 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2480 curproxy->state = PR_STNEW;
2481 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002482 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2483 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002484 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002485
2486 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002487 unsigned int low, high;
2488
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002489 if (strcmp(args[cur_arg], "all") == 0) {
2490 set = 0;
2491 break;
2492 }
2493 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002494 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002495 }
2496 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002497 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002498 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002499 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002500 char *dash = strchr(args[cur_arg], '-');
2501
2502 low = high = str2uic(args[cur_arg]);
2503 if (dash)
2504 high = str2uic(dash + 1);
2505
2506 if (high < low) {
2507 unsigned int swap = low;
2508 low = high;
2509 high = swap;
2510 }
2511
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002512 if (low < 1 || high > LONGBITS) {
2513 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2514 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002515 err_code |= ERR_ALERT | ERR_FATAL;
2516 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002517 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002518 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002519 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002520 }
2521 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002522 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2523 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002524 err_code |= ERR_ALERT | ERR_FATAL;
2525 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002526 }
2527 cur_arg++;
2528 }
2529 curproxy->bind_proc = set;
2530 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002531 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002532 if (curproxy == &defproxy) {
2533 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002534 err_code |= ERR_ALERT | ERR_FATAL;
2535 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002536 }
2537
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002538 err = invalid_char(args[1]);
2539 if (err) {
2540 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2541 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002543 }
2544
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002545 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002546 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2547 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
2549 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002550 }
2551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2553 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554
Willy Tarreau977b8e42006-12-29 14:19:17 +01002555 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002556 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002557
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 if (*(args[1]) == 0) {
2559 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2560 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_FATAL;
2562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002564
Willy Tarreau67402132012-05-31 20:40:20 +02002565 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002566 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002567 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002568 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002569 curproxy->cookie_name = strdup(args[1]);
2570 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002571
Willy Tarreaubaaee002006-06-26 02:48:02 +02002572 cur_arg = 2;
2573 while (*(args[cur_arg])) {
2574 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002575 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
2577 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002578 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
2580 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002581 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002582 }
2583 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002584 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 }
2586 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002587 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002589 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002590 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002593 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002594 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002595 else if (!strcmp(args[cur_arg], "httponly")) {
2596 curproxy->ck_opts |= PR_CK_HTTPONLY;
2597 }
2598 else if (!strcmp(args[cur_arg], "secure")) {
2599 curproxy->ck_opts |= PR_CK_SECURE;
2600 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002601 else if (!strcmp(args[cur_arg], "domain")) {
2602 if (!*args[cur_arg + 1]) {
2603 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2604 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002605 err_code |= ERR_ALERT | ERR_FATAL;
2606 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002607 }
2608
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002609 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002610 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002611 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2612 " dots nor does not start with a dot."
2613 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002614 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002615 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002616 }
2617
2618 err = invalid_domainchar(args[cur_arg + 1]);
2619 if (err) {
2620 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2621 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002624 }
2625
Willy Tarreau68a897b2009-12-03 23:28:34 +01002626 if (!curproxy->cookie_domain) {
2627 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2628 } else {
2629 /* one domain was already specified, add another one by
2630 * building the string which will be returned along with
2631 * the cookie.
2632 */
2633 char *new_ptr;
2634 int new_len = strlen(curproxy->cookie_domain) +
2635 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2636 new_ptr = malloc(new_len);
2637 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2638 free(curproxy->cookie_domain);
2639 curproxy->cookie_domain = new_ptr;
2640 }
Willy Tarreau31936852010-10-06 16:59:56 +02002641 cur_arg++;
2642 }
2643 else if (!strcmp(args[cur_arg], "maxidle")) {
2644 unsigned int maxidle;
2645 const char *res;
2646
2647 if (!*args[cur_arg + 1]) {
2648 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2649 file, linenum, args[cur_arg]);
2650 err_code |= ERR_ALERT | ERR_FATAL;
2651 goto out;
2652 }
2653
2654 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2655 if (res) {
2656 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2657 file, linenum, *res, args[cur_arg]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661 curproxy->cookie_maxidle = maxidle;
2662 cur_arg++;
2663 }
2664 else if (!strcmp(args[cur_arg], "maxlife")) {
2665 unsigned int maxlife;
2666 const char *res;
2667
2668 if (!*args[cur_arg + 1]) {
2669 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2670 file, linenum, args[cur_arg]);
2671 err_code |= ERR_ALERT | ERR_FATAL;
2672 goto out;
2673 }
2674
2675 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2676 if (res) {
2677 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2678 file, linenum, *res, args[cur_arg]);
2679 err_code |= ERR_ALERT | ERR_FATAL;
2680 goto out;
2681 }
2682 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002683 cur_arg++;
2684 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002686 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 +02002687 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002688 err_code |= ERR_ALERT | ERR_FATAL;
2689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002690 }
2691 cur_arg++;
2692 }
Willy Tarreau67402132012-05-31 20:40:20 +02002693 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2695 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002696 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697 }
2698
Willy Tarreau67402132012-05-31 20:40:20 +02002699 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002700 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2701 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002703 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002704
Willy Tarreau67402132012-05-31 20:40:20 +02002705 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002706 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2707 file, linenum);
2708 err_code |= ERR_ALERT | ERR_FATAL;
2709 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002710 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002711 else if (!strcmp(args[0], "persist")) { /* persist */
2712 if (*(args[1]) == 0) {
2713 Alert("parsing [%s:%d] : missing persist method.\n",
2714 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002715 err_code |= ERR_ALERT | ERR_FATAL;
2716 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002717 }
2718
2719 if (!strncmp(args[1], "rdp-cookie", 10)) {
2720 curproxy->options2 |= PR_O2_RDPC_PRST;
2721
Emeric Brunb982a3d2010-01-04 15:45:53 +01002722 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002723 const char *beg, *end;
2724
2725 beg = args[1] + 11;
2726 end = strchr(beg, ')');
2727
2728 if (!end || end == beg) {
2729 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2730 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002731 err_code |= ERR_ALERT | ERR_FATAL;
2732 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002733 }
2734
2735 free(curproxy->rdp_cookie_name);
2736 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2737 curproxy->rdp_cookie_len = end-beg;
2738 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002739 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002740 free(curproxy->rdp_cookie_name);
2741 curproxy->rdp_cookie_name = strdup("msts");
2742 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2743 }
2744 else { /* syntax */
2745 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2746 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002747 err_code |= ERR_ALERT | ERR_FATAL;
2748 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002749 }
2750 }
2751 else {
2752 Alert("parsing [%s:%d] : unknown persist method.\n",
2753 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002754 err_code |= ERR_ALERT | ERR_FATAL;
2755 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002756 }
2757 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002759 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002761 if (curproxy == &defproxy) {
2762 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2763 err_code |= ERR_ALERT | ERR_FATAL;
2764 goto out;
2765 }
2766
Willy Tarreau977b8e42006-12-29 14:19:17 +01002767 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002768 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002769
Willy Tarreaubaaee002006-06-26 02:48:02 +02002770 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002771 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
2774 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
2776 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002777 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002778 curproxy->appsession_name = strdup(args[1]);
2779 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2780 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002781 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2782 if (err) {
2783 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2784 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002787 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002788 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002789
Willy Tarreau51041c72007-09-09 21:56:53 +02002790 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2791 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_ABORT;
2793 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002795
2796 cur_arg = 6;
2797 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002798 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2799 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002800 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002801 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002802 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002803 } else if (!strcmp(args[cur_arg], "prefix")) {
2804 curproxy->options2 |= PR_O2_AS_PFX;
2805 } else if (!strcmp(args[cur_arg], "mode")) {
2806 if (!*args[cur_arg + 1]) {
2807 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2808 file, linenum, args[0], args[cur_arg]);
2809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
2811 }
2812
2813 cur_arg++;
2814 if (!strcmp(args[cur_arg], "query-string")) {
2815 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2816 curproxy->options2 |= PR_O2_AS_M_QS;
2817 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2818 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2819 curproxy->options2 |= PR_O2_AS_M_PP;
2820 } else {
2821 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2822 err_code |= ERR_ALERT | ERR_FATAL;
2823 goto out;
2824 }
2825 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002826 cur_arg++;
2827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 } /* Url App Session */
2829 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002830 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002831 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002832
Willy Tarreaubaaee002006-06-26 02:48:02 +02002833 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002834 if (curproxy == &defproxy) {
2835 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2836 err_code |= ERR_ALERT | ERR_FATAL;
2837 goto out;
2838 }
2839
Willy Tarreaubaaee002006-06-26 02:48:02 +02002840 if (*(args[4]) == 0) {
2841 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2842 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002843 err_code |= ERR_ALERT | ERR_FATAL;
2844 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002845 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002846 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 curproxy->capture_name = strdup(args[2]);
2848 curproxy->capture_namelen = strlen(curproxy->capture_name);
2849 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002850 curproxy->to_log |= LW_COOKIE;
2851 }
2852 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2853 struct cap_hdr *hdr;
2854
2855 if (curproxy == &defproxy) {
2856 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 +02002857 err_code |= ERR_ALERT | ERR_FATAL;
2858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859 }
2860
2861 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2862 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2863 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002864 err_code |= ERR_ALERT | ERR_FATAL;
2865 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002866 }
2867
2868 hdr = calloc(sizeof(struct cap_hdr), 1);
2869 hdr->next = curproxy->req_cap;
2870 hdr->name = strdup(args[3]);
2871 hdr->namelen = strlen(args[3]);
2872 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002873 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 hdr->index = curproxy->nb_req_cap++;
2875 curproxy->req_cap = hdr;
2876 curproxy->to_log |= LW_REQHDR;
2877 }
2878 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2879 struct cap_hdr *hdr;
2880
2881 if (curproxy == &defproxy) {
2882 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 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
2884 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002885 }
2886
2887 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2888 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2889 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002890 err_code |= ERR_ALERT | ERR_FATAL;
2891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 }
2893 hdr = calloc(sizeof(struct cap_hdr), 1);
2894 hdr->next = curproxy->rsp_cap;
2895 hdr->name = strdup(args[3]);
2896 hdr->namelen = strlen(args[3]);
2897 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002898 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002899 hdr->index = curproxy->nb_rsp_cap++;
2900 curproxy->rsp_cap = hdr;
2901 curproxy->to_log |= LW_RSPHDR;
2902 }
2903 else {
2904 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2905 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002906 err_code |= ERR_ALERT | ERR_FATAL;
2907 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002908 }
2909 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002910 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002911 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002912 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002913
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 if (*(args[1]) == 0) {
2915 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2916 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002917 err_code |= ERR_ALERT | ERR_FATAL;
2918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002919 }
2920 curproxy->conn_retries = atol(args[1]);
2921 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002922 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002923 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002924
2925 if (curproxy == &defproxy) {
2926 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2927 err_code |= ERR_ALERT | ERR_FATAL;
2928 goto out;
2929 }
2930
Willy Tarreau20b0de52012-12-24 15:45:22 +01002931 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2932 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2933 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2934 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002935 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002936 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2937 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 +01002938 file, linenum, args[0]);
2939 err_code |= ERR_WARN;
2940 }
2941
Willy Tarreauff011f22011-01-06 17:51:27 +01002942 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002943
Willy Tarreauff011f22011-01-06 17:51:27 +01002944 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002945 err_code |= ERR_ALERT | ERR_ABORT;
2946 goto out;
2947 }
2948
Willy Tarreau5002f572014-04-23 01:32:02 +02002949 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002950 err_code |= warnif_cond_conflicts(rule->cond,
2951 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2952 file, linenum);
2953
Willy Tarreauff011f22011-01-06 17:51:27 +01002954 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002955 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002956 else if (!strcmp(args[0], "http-response")) { /* response access control */
2957 struct http_res_rule *rule;
2958
2959 if (curproxy == &defproxy) {
2960 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964
2965 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2966 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2967 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2968 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2969 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2970 file, linenum, args[0]);
2971 err_code |= ERR_WARN;
2972 }
2973
2974 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2975
2976 if (!rule) {
2977 err_code |= ERR_ALERT | ERR_ABORT;
2978 goto out;
2979 }
2980
2981 err_code |= warnif_cond_conflicts(rule->cond,
2982 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2983 file, linenum);
2984
2985 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2986 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002987 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2988 /* set the header name and length into the proxy structure */
2989 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2990 err_code |= ERR_WARN;
2991
2992 if (!*args[1]) {
2993 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2994 file, linenum, args[0]);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998
2999 /* set the desired header name */
3000 free(curproxy->server_id_hdr_name);
3001 curproxy->server_id_hdr_name = strdup(args[1]);
3002 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3003 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003004 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003005 struct http_req_rule *rule;
3006
Willy Tarreaub099aca2008-10-12 17:26:37 +02003007 if (curproxy == &defproxy) {
3008 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003009 err_code |= ERR_ALERT | ERR_FATAL;
3010 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003011 }
3012
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003013 /* emulate "block" using "http-request block". Since these rules are supposed to
3014 * be processed before all http-request rules, we put them into their own list
3015 * and will insert them at the end.
3016 */
3017 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3018 if (!rule) {
3019 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003020 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003021 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003022 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3023 err_code |= warnif_cond_conflicts(rule->cond,
3024 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3025 file, linenum);
3026 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003027
3028 if (!already_warned(WARN_BLOCK_DEPRECATED))
3029 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]);
3030
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003031 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003032 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003033 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003034
Cyril Bonté99ed3272010-01-24 23:29:44 +01003035 if (curproxy == &defproxy) {
3036 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
3039 }
3040
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003041 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003042 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3043 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003046 }
3047
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003048 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003049 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003050 err_code |= warnif_cond_conflicts(rule->cond,
3051 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3052 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003053 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003054 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003055 struct switching_rule *rule;
3056
Willy Tarreaub099aca2008-10-12 17:26:37 +02003057 if (curproxy == &defproxy) {
3058 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003061 }
3062
Willy Tarreau55ea7572007-06-17 19:56:27 +02003063 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003064 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003065
3066 if (*(args[1]) == 0) {
3067 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_ALERT | ERR_FATAL;
3069 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003070 }
3071
Willy Tarreauf51658d2014-04-23 01:21:56 +02003072 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3073 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3074 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3075 file, linenum, errmsg);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
3078 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003079
Willy Tarreauf51658d2014-04-23 01:21:56 +02003080 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003081 }
3082
3083 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3084 rule->cond = cond;
3085 rule->be.name = strdup(args[1]);
3086 LIST_INIT(&rule->list);
3087 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3088 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003089 else if (strcmp(args[0], "use-server") == 0) {
3090 struct server_rule *rule;
3091
3092 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
3098 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3099 err_code |= ERR_WARN;
3100
3101 if (*(args[1]) == 0) {
3102 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106
3107 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3108 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3109 file, linenum, args[0]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003114 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3115 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3116 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003121 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003122
3123 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3124 rule->cond = cond;
3125 rule->srv.name = strdup(args[1]);
3126 LIST_INIT(&rule->list);
3127 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3128 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3129 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003130 else if ((!strcmp(args[0], "force-persist")) ||
3131 (!strcmp(args[0], "ignore-persist"))) {
3132 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003133
3134 if (curproxy == &defproxy) {
3135 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3136 err_code |= ERR_ALERT | ERR_FATAL;
3137 goto out;
3138 }
3139
3140 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3141 err_code |= ERR_WARN;
3142
Willy Tarreauef6494c2010-01-28 17:12:36 +01003143 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003144 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3145 file, linenum, args[0]);
3146 err_code |= ERR_ALERT | ERR_FATAL;
3147 goto out;
3148 }
3149
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003150 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3151 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3152 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
3155 }
3156
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003157 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3158 * where force-persist is applied.
3159 */
3160 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003161
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003162 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003163 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003164 if (!strcmp(args[0], "force-persist")) {
3165 rule->type = PERSIST_TYPE_FORCE;
3166 } else {
3167 rule->type = PERSIST_TYPE_IGNORE;
3168 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003169 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003170 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003171 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003172 else if (!strcmp(args[0], "stick-table")) {
3173 int myidx = 1;
3174
Emeric Brun32da3c42010-09-23 18:39:19 +02003175 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003176 curproxy->table.type = (unsigned int)-1;
3177 while (*args[myidx]) {
3178 const char *err;
3179
3180 if (strcmp(args[myidx], "size") == 0) {
3181 myidx++;
3182 if (!*(args[myidx])) {
3183 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3184 file, linenum, args[myidx-1]);
3185 err_code |= ERR_ALERT | ERR_FATAL;
3186 goto out;
3187 }
3188 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3189 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3190 file, linenum, *err, args[myidx-1]);
3191 err_code |= ERR_ALERT | ERR_FATAL;
3192 goto out;
3193 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003194 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003195 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003196 else if (strcmp(args[myidx], "peers") == 0) {
3197 myidx++;
Godbach50523162013-12-11 19:48:57 +08003198 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003199 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3200 file, linenum, args[myidx-1]);
3201 err_code |= ERR_ALERT | ERR_FATAL;
3202 goto out;
Godbach50523162013-12-11 19:48:57 +08003203 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003204 curproxy->table.peers.name = strdup(args[myidx++]);
3205 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003206 else if (strcmp(args[myidx], "expire") == 0) {
3207 myidx++;
3208 if (!*(args[myidx])) {
3209 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3210 file, linenum, args[myidx-1]);
3211 err_code |= ERR_ALERT | ERR_FATAL;
3212 goto out;
3213 }
3214 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3215 if (err) {
3216 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3217 file, linenum, *err, args[myidx-1]);
3218 err_code |= ERR_ALERT | ERR_FATAL;
3219 goto out;
3220 }
Ben Cabot85a1c182016-01-20 09:44:39 +00003221 if (val > INT_MAX) {
3222 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3223 file, linenum, val);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003227 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003228 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003229 }
3230 else if (strcmp(args[myidx], "nopurge") == 0) {
3231 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003232 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 }
3234 else if (strcmp(args[myidx], "type") == 0) {
3235 myidx++;
3236 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3237 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3238 file, linenum, args[myidx]);
3239 err_code |= ERR_ALERT | ERR_FATAL;
3240 goto out;
3241 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003242 /* myidx already points to next arg */
3243 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003244 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003245 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003246 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003247
3248 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003249 nw = args[myidx];
3250 while (*nw) {
3251 /* the "store" keyword supports a comma-separated list */
3252 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003253 sa = NULL; /* store arg */
3254 while (*nw && *nw != ',') {
3255 if (*nw == '(') {
3256 *nw = 0;
3257 sa = ++nw;
3258 while (*nw != ')') {
3259 if (!*nw) {
3260 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3261 file, linenum, args[0], cw);
3262 err_code |= ERR_ALERT | ERR_FATAL;
3263 goto out;
3264 }
3265 nw++;
3266 }
3267 *nw = '\0';
3268 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003269 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003270 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003271 if (*nw)
3272 *nw++ = '\0';
3273 type = stktable_get_data_type(cw);
3274 if (type < 0) {
3275 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3276 file, linenum, args[0], cw);
3277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
3279 }
Willy Tarreauac782882010-06-20 10:41:54 +02003280
3281 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3282 switch (err) {
3283 case PE_NONE: break;
3284 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003285 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3286 file, linenum, args[0], cw);
3287 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003288 break;
3289
3290 case PE_ARG_MISSING:
3291 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3292 file, linenum, args[0], cw);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295
3296 case PE_ARG_NOT_USED:
3297 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3298 file, linenum, args[0], cw);
3299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
3301
3302 default:
3303 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3304 file, linenum, args[0], cw);
3305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003307 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003308 }
3309 myidx++;
3310 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003311 else {
3312 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3313 file, linenum, args[myidx]);
3314 err_code |= ERR_ALERT | ERR_FATAL;
3315 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003316 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003317 }
3318
3319 if (!curproxy->table.size) {
3320 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3321 file, linenum);
3322 err_code |= ERR_ALERT | ERR_FATAL;
3323 goto out;
3324 }
3325
3326 if (curproxy->table.type == (unsigned int)-1) {
3327 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3328 file, linenum);
3329 err_code |= ERR_ALERT | ERR_FATAL;
3330 goto out;
3331 }
3332 }
3333 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003334 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003335 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003336 int myidx = 0;
3337 const char *name = NULL;
3338 int flags;
3339
3340 if (curproxy == &defproxy) {
3341 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3342 err_code |= ERR_ALERT | ERR_FATAL;
3343 goto out;
3344 }
3345
3346 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3347 err_code |= ERR_WARN;
3348 goto out;
3349 }
3350
3351 myidx++;
3352 if ((strcmp(args[myidx], "store") == 0) ||
3353 (strcmp(args[myidx], "store-request") == 0)) {
3354 myidx++;
3355 flags = STK_IS_STORE;
3356 }
3357 else if (strcmp(args[myidx], "store-response") == 0) {
3358 myidx++;
3359 flags = STK_IS_STORE | STK_ON_RSP;
3360 }
3361 else if (strcmp(args[myidx], "match") == 0) {
3362 myidx++;
3363 flags = STK_IS_MATCH;
3364 }
3365 else if (strcmp(args[myidx], "on") == 0) {
3366 myidx++;
3367 flags = STK_IS_MATCH | STK_IS_STORE;
3368 }
3369 else {
3370 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3371 err_code |= ERR_ALERT | ERR_FATAL;
3372 goto out;
3373 }
3374
3375 if (*(args[myidx]) == 0) {
3376 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3377 err_code |= ERR_ALERT | ERR_FATAL;
3378 goto out;
3379 }
3380
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003381 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003382 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003383 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003384 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003385 err_code |= ERR_ALERT | ERR_FATAL;
3386 goto out;
3387 }
3388
3389 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003390 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3391 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3392 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003393 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003394 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003395 goto out;
3396 }
3397 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003398 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3399 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3400 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003401 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003402 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003403 goto out;
3404 }
3405 }
3406
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003407 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003408 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003409
Emeric Brunb982a3d2010-01-04 15:45:53 +01003410 if (strcmp(args[myidx], "table") == 0) {
3411 myidx++;
3412 name = args[myidx++];
3413 }
3414
Willy Tarreauef6494c2010-01-28 17:12:36 +01003415 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003416 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3417 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3418 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003419 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003420 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003421 goto out;
3422 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003423 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003424 else if (*(args[myidx])) {
3425 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3426 file, linenum, args[0], args[myidx]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003428 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003429 goto out;
3430 }
Emeric Brun97679e72010-09-23 17:56:44 +02003431 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003432 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003433 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003434 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003435
Emeric Brunb982a3d2010-01-04 15:45:53 +01003436 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3437 rule->cond = cond;
3438 rule->expr = expr;
3439 rule->flags = flags;
3440 rule->table.name = name ? strdup(name) : NULL;
3441 LIST_INIT(&rule->list);
3442 if (flags & STK_ON_RSP)
3443 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3444 else
3445 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 else if (!strcmp(args[0], "stats")) {
3448 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3449 curproxy->uri_auth = NULL; /* we must detach from the default config */
3450
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003451 if (!*args[1]) {
3452 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003453 } else if (!strcmp(args[1], "admin")) {
3454 struct stats_admin_rule *rule;
3455
3456 if (curproxy == &defproxy) {
3457 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3458 err_code |= ERR_ALERT | ERR_FATAL;
3459 goto out;
3460 }
3461
3462 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3463 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3464 err_code |= ERR_ALERT | ERR_ABORT;
3465 goto out;
3466 }
3467
3468 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3469 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3470 file, linenum, args[0], args[1]);
3471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
3473 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003474 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3475 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3476 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003477 err_code |= ERR_ALERT | ERR_FATAL;
3478 goto out;
3479 }
3480
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003481 err_code |= warnif_cond_conflicts(cond,
3482 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3483 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003484
3485 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3486 rule->cond = cond;
3487 LIST_INIT(&rule->list);
3488 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003489 } else if (!strcmp(args[1], "uri")) {
3490 if (*(args[2]) == 0) {
3491 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3495 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_ABORT;
3497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 }
3499 } else if (!strcmp(args[1], "realm")) {
3500 if (*(args[2]) == 0) {
3501 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3505 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_ABORT;
3507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003509 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003510 unsigned interval;
3511
3512 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3513 if (err) {
3514 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3515 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003516 err_code |= ERR_ALERT | ERR_FATAL;
3517 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003518 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3519 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_ABORT;
3521 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003522 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003523 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003524 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003525
3526 if (curproxy == &defproxy) {
3527 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3528 err_code |= ERR_ALERT | ERR_FATAL;
3529 goto out;
3530 }
3531
3532 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3533 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3534 err_code |= ERR_ALERT | ERR_ABORT;
3535 goto out;
3536 }
3537
Willy Tarreauff011f22011-01-06 17:51:27 +01003538 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3539 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003540 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3541 file, linenum, args[0]);
3542 err_code |= ERR_WARN;
3543 }
3544
Willy Tarreauff011f22011-01-06 17:51:27 +01003545 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003546
Willy Tarreauff011f22011-01-06 17:51:27 +01003547 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003548 err_code |= ERR_ALERT | ERR_ABORT;
3549 goto out;
3550 }
3551
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003552 err_code |= warnif_cond_conflicts(rule->cond,
3553 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3554 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003555 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003556
Willy Tarreaubaaee002006-06-26 02:48:02 +02003557 } else if (!strcmp(args[1], "auth")) {
3558 if (*(args[2]) == 0) {
3559 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003560 err_code |= ERR_ALERT | ERR_FATAL;
3561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003562 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3563 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_ABORT;
3565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 }
3567 } else if (!strcmp(args[1], "scope")) {
3568 if (*(args[2]) == 0) {
3569 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003572 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3573 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_ABORT;
3575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 }
3577 } else if (!strcmp(args[1], "enable")) {
3578 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3579 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003580 err_code |= ERR_ALERT | ERR_ABORT;
3581 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003583 } else if (!strcmp(args[1], "hide-version")) {
3584 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3585 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_ABORT;
3587 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003588 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003589 } else if (!strcmp(args[1], "show-legends")) {
3590 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3591 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3592 err_code |= ERR_ALERT | ERR_ABORT;
3593 goto out;
3594 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003595 } else if (!strcmp(args[1], "show-node")) {
3596
3597 if (*args[2]) {
3598 int i;
3599 char c;
3600
3601 for (i=0; args[2][i]; i++) {
3602 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003603 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3604 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003605 break;
3606 }
3607
3608 if (!i || args[2][i]) {
3609 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3610 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3611 file, linenum, args[0], args[1]);
3612 err_code |= ERR_ALERT | ERR_FATAL;
3613 goto out;
3614 }
3615 }
3616
3617 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3618 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3619 err_code |= ERR_ALERT | ERR_ABORT;
3620 goto out;
3621 }
3622 } else if (!strcmp(args[1], "show-desc")) {
3623 char *desc = NULL;
3624
3625 if (*args[2]) {
3626 int i, len=0;
3627 char *d;
3628
Willy Tarreau348acfe2014-04-14 15:00:39 +02003629 for (i = 2; *args[i]; i++)
3630 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003631
3632 desc = d = (char *)calloc(1, len);
3633
Willy Tarreau348acfe2014-04-14 15:00:39 +02003634 d += snprintf(d, desc + len - d, "%s", args[2]);
3635 for (i = 3; *args[i]; i++)
3636 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003637 }
3638
3639 if (!*args[2] && !global.desc)
3640 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3641 file, linenum, args[1]);
3642 else {
3643 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3644 free(desc);
3645 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3646 err_code |= ERR_ALERT | ERR_ABORT;
3647 goto out;
3648 }
3649 free(desc);
3650 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003651 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003652stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003653 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 +01003654 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003657 }
3658 }
3659 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003660 int optnum;
3661
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003662 if (*(args[1]) == '\0') {
3663 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3664 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003665 err_code |= ERR_ALERT | ERR_FATAL;
3666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003667 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003668
3669 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3670 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003671 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3672 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3673 file, linenum, cfg_opts[optnum].name);
3674 err_code |= ERR_ALERT | ERR_FATAL;
3675 goto out;
3676 }
Willy Tarreau93893792009-07-23 13:19:11 +02003677 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3678 err_code |= ERR_WARN;
3679 goto out;
3680 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003681
Willy Tarreau3842f002009-06-14 11:39:52 +02003682 curproxy->no_options &= ~cfg_opts[optnum].val;
3683 curproxy->options &= ~cfg_opts[optnum].val;
3684
3685 switch (kwm) {
3686 case KWM_STD:
3687 curproxy->options |= cfg_opts[optnum].val;
3688 break;
3689 case KWM_NO:
3690 curproxy->no_options |= cfg_opts[optnum].val;
3691 break;
3692 case KWM_DEF: /* already cleared */
3693 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003694 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003695
Willy Tarreau93893792009-07-23 13:19:11 +02003696 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003697 }
3698 }
3699
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003700 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3701 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003702 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3703 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3704 file, linenum, cfg_opts2[optnum].name);
3705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
3707 }
Willy Tarreau93893792009-07-23 13:19:11 +02003708 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3709 err_code |= ERR_WARN;
3710 goto out;
3711 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003712
Willy Tarreau3842f002009-06-14 11:39:52 +02003713 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3714 curproxy->options2 &= ~cfg_opts2[optnum].val;
3715
3716 switch (kwm) {
3717 case KWM_STD:
3718 curproxy->options2 |= cfg_opts2[optnum].val;
3719 break;
3720 case KWM_NO:
3721 curproxy->no_options2 |= cfg_opts2[optnum].val;
3722 break;
3723 case KWM_DEF: /* already cleared */
3724 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003725 }
Willy Tarreau93893792009-07-23 13:19:11 +02003726 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003727 }
3728 }
3729
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003730 /* HTTP options override each other. They can be cancelled using
3731 * "no option xxx" which only switches to default mode if the mode
3732 * was this one (useful for cancelling options set in defaults
3733 * sections).
3734 */
3735 if (strcmp(args[1], "httpclose") == 0) {
3736 if (kwm == KWM_STD) {
3737 curproxy->options &= ~PR_O_HTTP_MODE;
3738 curproxy->options |= PR_O_HTTP_PCL;
3739 goto out;
3740 }
3741 else if (kwm == KWM_NO) {
3742 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3743 curproxy->options &= ~PR_O_HTTP_MODE;
3744 goto out;
3745 }
3746 }
3747 else if (strcmp(args[1], "forceclose") == 0) {
3748 if (kwm == KWM_STD) {
3749 curproxy->options &= ~PR_O_HTTP_MODE;
3750 curproxy->options |= PR_O_HTTP_FCL;
3751 goto out;
3752 }
3753 else if (kwm == KWM_NO) {
3754 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3755 curproxy->options &= ~PR_O_HTTP_MODE;
3756 goto out;
3757 }
3758 }
3759 else if (strcmp(args[1], "http-server-close") == 0) {
3760 if (kwm == KWM_STD) {
3761 curproxy->options &= ~PR_O_HTTP_MODE;
3762 curproxy->options |= PR_O_HTTP_SCL;
3763 goto out;
3764 }
3765 else if (kwm == KWM_NO) {
3766 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3767 curproxy->options &= ~PR_O_HTTP_MODE;
3768 goto out;
3769 }
3770 }
3771 else if (strcmp(args[1], "http-keep-alive") == 0) {
3772 if (kwm == KWM_STD) {
3773 curproxy->options &= ~PR_O_HTTP_MODE;
3774 curproxy->options |= PR_O_HTTP_KAL;
3775 goto out;
3776 }
3777 else if (kwm == KWM_NO) {
3778 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3779 curproxy->options &= ~PR_O_HTTP_MODE;
3780 goto out;
3781 }
3782 }
3783 else if (strcmp(args[1], "http-tunnel") == 0) {
3784 if (kwm == KWM_STD) {
3785 curproxy->options &= ~PR_O_HTTP_MODE;
3786 curproxy->options |= PR_O_HTTP_TUN;
3787 goto out;
3788 }
3789 else if (kwm == KWM_NO) {
3790 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3791 curproxy->options &= ~PR_O_HTTP_MODE;
3792 goto out;
3793 }
3794 }
3795
Willy Tarreau3842f002009-06-14 11:39:52 +02003796 if (kwm != KWM_STD) {
3797 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003798 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003799 err_code |= ERR_ALERT | ERR_FATAL;
3800 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003801 }
3802
Emeric Brun3a058f32009-06-30 18:26:00 +02003803 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003804 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003805 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003806 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003807 if (*(args[2]) != '\0') {
3808 if (!strcmp(args[2], "clf")) {
3809 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003810 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003811 } else {
William Lallemand629b1c02015-05-28 18:02:48 +02003812 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003815 }
3816 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003817 if (curproxy->conf.logformat_string != default_http_log_format &&
3818 curproxy->conf.logformat_string != default_tcp_log_format &&
3819 curproxy->conf.logformat_string != clf_http_log_format)
3820 free(curproxy->conf.logformat_string);
3821 curproxy->conf.logformat_string = logformat;
3822
3823 free(curproxy->conf.lfs_file);
3824 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3825 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003826 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003827 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003828 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003829 if (curproxy->conf.logformat_string != default_http_log_format &&
3830 curproxy->conf.logformat_string != default_tcp_log_format &&
3831 curproxy->conf.logformat_string != clf_http_log_format)
3832 free(curproxy->conf.logformat_string);
3833 curproxy->conf.logformat_string = default_tcp_log_format;
3834
3835 free(curproxy->conf.lfs_file);
3836 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3837 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 else if (!strcmp(args[1], "tcpka")) {
3840 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003841 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003843
3844 if (curproxy->cap & PR_CAP_FE)
3845 curproxy->options |= PR_O_TCP_CLI_KA;
3846 if (curproxy->cap & PR_CAP_BE)
3847 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
3849 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003850 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003851 err_code |= ERR_WARN;
3852
Willy Tarreaubaaee002006-06-26 02:48:02 +02003853 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003854 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003855 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003856 curproxy->options2 &= ~PR_O2_CHK_ANY;
3857 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 if (!*args[2]) { /* no argument */
3859 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3860 curproxy->check_len = strlen(DEF_CHECK_REQ);
3861 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003862 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 curproxy->check_req = (char *)malloc(reqlen);
3864 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003865 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003866 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003867 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003868 if (*args[4])
3869 reqlen += strlen(args[4]);
3870 else
3871 reqlen += strlen("HTTP/1.0");
3872
3873 curproxy->check_req = (char *)malloc(reqlen);
3874 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003875 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003876 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003877 }
3878 else if (!strcmp(args[1], "ssl-hello-chk")) {
3879 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003880 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003881 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003882
Willy Tarreaua534fea2008-08-03 12:19:50 +02003883 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003884 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003885 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003886 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003887 }
Willy Tarreau23677902007-05-08 23:50:35 +02003888 else if (!strcmp(args[1], "smtpchk")) {
3889 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003890 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003891 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003892 curproxy->options2 &= ~PR_O2_CHK_ANY;
3893 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003894
3895 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3896 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3897 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3898 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3899 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3900 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3901 curproxy->check_req = (char *)malloc(reqlen);
3902 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3903 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3904 } else {
3905 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3906 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3907 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3908 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3909 }
3910 }
3911 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003912 else if (!strcmp(args[1], "pgsql-check")) {
3913 /* use PostgreSQL request to check servers' health */
3914 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3915 err_code |= ERR_WARN;
3916
3917 free(curproxy->check_req);
3918 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003919 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003920 curproxy->options2 |= PR_O2_PGSQL_CHK;
3921
3922 if (*(args[2])) {
3923 int cur_arg = 2;
3924
3925 while (*(args[cur_arg])) {
3926 if (strcmp(args[cur_arg], "user") == 0) {
3927 char * packet;
3928 uint32_t packet_len;
3929 uint32_t pv;
3930
3931 /* suboption header - needs additional argument for it */
3932 if (*(args[cur_arg+1]) == 0) {
3933 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3934 file, linenum, args[0], args[1], args[cur_arg]);
3935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938
3939 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3940 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3941 pv = htonl(0x30000); /* protocol version 3.0 */
3942
3943 packet = (char*) calloc(1, packet_len);
3944
3945 memcpy(packet + 4, &pv, 4);
3946
3947 /* copy "user" */
3948 memcpy(packet + 8, "user", 4);
3949
3950 /* copy username */
3951 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3952
3953 free(curproxy->check_req);
3954 curproxy->check_req = packet;
3955 curproxy->check_len = packet_len;
3956
3957 packet_len = htonl(packet_len);
3958 memcpy(packet, &packet_len, 4);
3959 cur_arg += 2;
3960 } else {
3961 /* unknown suboption - catchall */
3962 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3963 file, linenum, args[0], args[1]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967 } /* end while loop */
3968 }
3969 }
3970
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003971 else if (!strcmp(args[1], "redis-check")) {
3972 /* use REDIS PING request to check servers' health */
3973 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3974 err_code |= ERR_WARN;
3975
3976 free(curproxy->check_req);
3977 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003978 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003979 curproxy->options2 |= PR_O2_REDIS_CHK;
3980
3981 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3982 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3983 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3984 }
3985
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003986 else if (!strcmp(args[1], "mysql-check")) {
3987 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003988 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3989 err_code |= ERR_WARN;
3990
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003991 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003992 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003993 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003994 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003995
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003996 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003997 * const char mysql40_client_auth_pkt[] = {
3998 * "\x0e\x00\x00" // packet length
3999 * "\x01" // packet number
4000 * "\x00\x00" // client capabilities
4001 * "\x00\x00\x01" // max packet
4002 * "haproxy\x00" // username (null terminated string)
4003 * "\x00" // filler (always 0x00)
4004 * "\x01\x00\x00" // packet length
4005 * "\x00" // packet number
4006 * "\x01" // COM_QUIT command
4007 * };
4008 */
4009
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004010 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4011 * const char mysql41_client_auth_pkt[] = {
4012 * "\x0e\x00\x00\" // packet length
4013 * "\x01" // packet number
4014 * "\x00\x00\x00\x00" // client capabilities
4015 * "\x00\x00\x00\x01" // max packet
4016 * "\x21" // character set (UTF-8)
4017 * char[23] // All zeroes
4018 * "haproxy\x00" // username (null terminated string)
4019 * "\x00" // filler (always 0x00)
4020 * "\x01\x00\x00" // packet length
4021 * "\x00" // packet number
4022 * "\x01" // COM_QUIT command
4023 * };
4024 */
4025
4026
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004027 if (*(args[2])) {
4028 int cur_arg = 2;
4029
4030 while (*(args[cur_arg])) {
4031 if (strcmp(args[cur_arg], "user") == 0) {
4032 char *mysqluser;
4033 int packetlen, reqlen, userlen;
4034
4035 /* suboption header - needs additional argument for it */
4036 if (*(args[cur_arg+1]) == 0) {
4037 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4038 file, linenum, args[0], args[1], args[cur_arg]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042 mysqluser = args[cur_arg + 1];
4043 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004044
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004045 if (*(args[cur_arg+2])) {
4046 if (!strcmp(args[cur_arg+2], "post-41")) {
4047 packetlen = userlen + 7 + 27;
4048 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004049
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004050 free(curproxy->check_req);
4051 curproxy->check_req = (char *)calloc(1, reqlen);
4052 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004053
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004054 snprintf(curproxy->check_req, 4, "%c%c%c",
4055 ((unsigned char) packetlen & 0xff),
4056 ((unsigned char) (packetlen >> 8) & 0xff),
4057 ((unsigned char) (packetlen >> 16) & 0xff));
4058
4059 curproxy->check_req[3] = 1;
4060 curproxy->check_req[5] = 130;
4061 curproxy->check_req[11] = 1;
4062 curproxy->check_req[12] = 33;
4063 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4064 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4065 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4066 cur_arg += 3;
4067 } else {
4068 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4069 err_code |= ERR_ALERT | ERR_FATAL;
4070 goto out;
4071 }
4072 } else {
4073 packetlen = userlen + 7;
4074 reqlen = packetlen + 9;
4075
4076 free(curproxy->check_req);
4077 curproxy->check_req = (char *)calloc(1, reqlen);
4078 curproxy->check_len = reqlen;
4079
4080 snprintf(curproxy->check_req, 4, "%c%c%c",
4081 ((unsigned char) packetlen & 0xff),
4082 ((unsigned char) (packetlen >> 8) & 0xff),
4083 ((unsigned char) (packetlen >> 16) & 0xff));
4084
4085 curproxy->check_req[3] = 1;
4086 curproxy->check_req[5] = 128;
4087 curproxy->check_req[8] = 1;
4088 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4089 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4090 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4091 cur_arg += 2;
4092 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004093 } else {
4094 /* unknown suboption - catchall */
4095 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4096 file, linenum, args[0], args[1]);
4097 err_code |= ERR_ALERT | ERR_FATAL;
4098 goto out;
4099 }
4100 } /* end while loop */
4101 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004102 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004103 else if (!strcmp(args[1], "ldap-check")) {
4104 /* use LDAP request to check servers' health */
4105 free(curproxy->check_req);
4106 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004107 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004108 curproxy->options2 |= PR_O2_LDAP_CHK;
4109
4110 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4111 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4112 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4113 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004114 else if (!strcmp(args[1], "tcp-check")) {
4115 /* use raw TCPCHK send/expect to check servers' health */
4116 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4117 err_code |= ERR_WARN;
4118
4119 free(curproxy->check_req);
4120 curproxy->check_req = NULL;
4121 curproxy->options2 &= ~PR_O2_CHK_ANY;
4122 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4123 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004124 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004125 int cur_arg;
4126
4127 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4128 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004129 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004130
Willy Tarreau87cf5142011-08-19 22:57:24 +02004131 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004132
4133 free(curproxy->fwdfor_hdr_name);
4134 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4135 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4136
4137 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4138 cur_arg = 2;
4139 while (*(args[cur_arg])) {
4140 if (!strcmp(args[cur_arg], "except")) {
4141 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004142 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004143 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4144 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004145 err_code |= ERR_ALERT | ERR_FATAL;
4146 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004147 }
4148 /* flush useless bits */
4149 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004150 cur_arg += 2;
4151 } else if (!strcmp(args[cur_arg], "header")) {
4152 /* suboption header - needs additional argument for it */
4153 if (*(args[cur_arg+1]) == 0) {
4154 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4155 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004158 }
4159 free(curproxy->fwdfor_hdr_name);
4160 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4161 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4162 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004163 } else if (!strcmp(args[cur_arg], "if-none")) {
4164 curproxy->options &= ~PR_O_FF_ALWAYS;
4165 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004166 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004167 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004168 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004169 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004170 err_code |= ERR_ALERT | ERR_FATAL;
4171 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004172 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004173 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004174 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004175 else if (!strcmp(args[1], "originalto")) {
4176 int cur_arg;
4177
4178 /* insert x-original-to field, but not for the IP address listed as an except.
4179 * set default options (ie: bitfield, header name, etc)
4180 */
4181
4182 curproxy->options |= PR_O_ORGTO;
4183
4184 free(curproxy->orgto_hdr_name);
4185 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4186 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4187
Willy Tarreau87cf5142011-08-19 22:57:24 +02004188 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004189 cur_arg = 2;
4190 while (*(args[cur_arg])) {
4191 if (!strcmp(args[cur_arg], "except")) {
4192 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004193 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 +02004194 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4195 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004196 err_code |= ERR_ALERT | ERR_FATAL;
4197 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004198 }
4199 /* flush useless bits */
4200 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4201 cur_arg += 2;
4202 } else if (!strcmp(args[cur_arg], "header")) {
4203 /* suboption header - needs additional argument for it */
4204 if (*(args[cur_arg+1]) == 0) {
4205 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4206 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004207 err_code |= ERR_ALERT | ERR_FATAL;
4208 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004209 }
4210 free(curproxy->orgto_hdr_name);
4211 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4212 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4213 cur_arg += 2;
4214 } else {
4215 /* unknown suboption - catchall */
4216 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4217 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004218 err_code |= ERR_ALERT | ERR_FATAL;
4219 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004220 }
4221 } /* end while loop */
4222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004223 else {
4224 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_ALERT | ERR_FATAL;
4226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 }
Willy Tarreau93893792009-07-23 13:19:11 +02004228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004230 else if (!strcmp(args[0], "default_backend")) {
4231 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004232 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004233
4234 if (*(args[1]) == 0) {
4235 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_ALERT | ERR_FATAL;
4237 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004238 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004239 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004240 curproxy->defbe.name = strdup(args[1]);
4241 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004242 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004243 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004244 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004245
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004246 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4247 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 +01004248 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004250 /* enable reconnections to dispatch */
4251 curproxy->options |= PR_O_REDISP;
4252 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004253 else if (!strcmp(args[0], "http-check")) {
4254 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004255 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004256
4257 if (strcmp(args[1], "disable-on-404") == 0) {
4258 /* enable a graceful server shutdown on an HTTP 404 response */
4259 curproxy->options |= PR_O_DISABLE404;
4260 }
Willy Tarreauef781042010-01-27 11:53:01 +01004261 else if (strcmp(args[1], "send-state") == 0) {
4262 /* enable emission of the apparent state of a server in HTTP checks */
4263 curproxy->options2 |= PR_O2_CHK_SNDST;
4264 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004265 else if (strcmp(args[1], "expect") == 0) {
4266 const char *ptr_arg;
4267 int cur_arg;
4268
4269 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4270 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4271 err_code |= ERR_ALERT | ERR_FATAL;
4272 goto out;
4273 }
4274
4275 cur_arg = 2;
4276 /* consider exclamation marks, sole or at the beginning of a word */
4277 while (*(ptr_arg = args[cur_arg])) {
4278 while (*ptr_arg == '!') {
4279 curproxy->options2 ^= PR_O2_EXP_INV;
4280 ptr_arg++;
4281 }
4282 if (*ptr_arg)
4283 break;
4284 cur_arg++;
4285 }
4286 /* now ptr_arg points to the beginning of a word past any possible
4287 * exclamation mark, and cur_arg is the argument which holds this word.
4288 */
4289 if (strcmp(ptr_arg, "status") == 0) {
4290 if (!*(args[cur_arg + 1])) {
4291 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4292 file, linenum, args[0], args[1], ptr_arg);
4293 err_code |= ERR_ALERT | ERR_FATAL;
4294 goto out;
4295 }
4296 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004297 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004298 curproxy->expect_str = strdup(args[cur_arg + 1]);
4299 }
4300 else if (strcmp(ptr_arg, "string") == 0) {
4301 if (!*(args[cur_arg + 1])) {
4302 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4303 file, linenum, args[0], args[1], ptr_arg);
4304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004308 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004309 curproxy->expect_str = strdup(args[cur_arg + 1]);
4310 }
4311 else if (strcmp(ptr_arg, "rstatus") == 0) {
4312 if (!*(args[cur_arg + 1])) {
4313 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4314 file, linenum, args[0], args[1], ptr_arg);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004319 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004320 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004321 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004322 free(curproxy->expect_regex);
4323 curproxy->expect_regex = NULL;
4324 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004325 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004326 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4327 error = NULL;
4328 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4329 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4330 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4331 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004332 err_code |= ERR_ALERT | ERR_FATAL;
4333 goto out;
4334 }
4335 }
4336 else if (strcmp(ptr_arg, "rstring") == 0) {
4337 if (!*(args[cur_arg + 1])) {
4338 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4339 file, linenum, args[0], args[1], ptr_arg);
4340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342 }
4343 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004344 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004345 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004346 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004347 free(curproxy->expect_regex);
4348 curproxy->expect_regex = NULL;
4349 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004350 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004351 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4352 error = NULL;
4353 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4354 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4355 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4356 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004357 err_code |= ERR_ALERT | ERR_FATAL;
4358 goto out;
4359 }
4360 }
4361 else {
4362 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4363 file, linenum, args[0], args[1], ptr_arg);
4364 err_code |= ERR_ALERT | ERR_FATAL;
4365 goto out;
4366 }
4367 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004368 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004369 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 +02004370 err_code |= ERR_ALERT | ERR_FATAL;
4371 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004372 }
4373 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004374 else if (!strcmp(args[0], "tcp-check")) {
4375 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4376 err_code |= ERR_WARN;
4377
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004378 if (strcmp(args[1], "connect") == 0) {
4379 const char *ptr_arg;
4380 int cur_arg;
4381 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004382
4383 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004384 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004385
Willy Tarreau5bff0592015-05-13 12:24:53 +02004386 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4387 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4388 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4389 file, linenum);
4390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004392 }
4393
4394 cur_arg = 2;
4395 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4396 tcpcheck->action = TCPCHK_ACT_CONNECT;
4397
4398 /* parsing each parameters to fill up the rule */
4399 while (*(ptr_arg = args[cur_arg])) {
4400 /* tcp port */
4401 if (strcmp(args[cur_arg], "port") == 0) {
4402 if ( (atol(args[cur_arg + 1]) > 65535) ||
4403 (atol(args[cur_arg + 1]) < 1) ){
4404 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4405 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4406 err_code |= ERR_ALERT | ERR_FATAL;
4407 goto out;
4408 }
4409 tcpcheck->port = atol(args[cur_arg + 1]);
4410 cur_arg += 2;
4411 }
4412 /* send proxy protocol */
4413 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4414 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4415 cur_arg++;
4416 }
4417#ifdef USE_OPENSSL
4418 else if (strcmp(args[cur_arg], "ssl") == 0) {
4419 curproxy->options |= PR_O_TCPCHK_SSL;
4420 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4421 cur_arg++;
4422 }
4423#endif /* USE_OPENSSL */
4424 else {
4425#ifdef USE_OPENSSL
4426 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4427#else /* USE_OPENSSL */
4428 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4429#endif /* USE_OPENSSL */
4430 file, linenum, args[0], args[1], args[cur_arg]);
4431 err_code |= ERR_ALERT | ERR_FATAL;
4432 goto out;
4433 }
4434
4435 }
4436
4437 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4438 }
4439 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004440 if (! *(args[2]) ) {
4441 /* SEND string expected */
4442 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4443 file, linenum, args[0], args[1], args[2]);
4444 err_code |= ERR_ALERT | ERR_FATAL;
4445 goto out;
4446 } else {
4447 struct tcpcheck_rule *tcpcheck;
4448
4449 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4450
4451 tcpcheck->action = TCPCHK_ACT_SEND;
4452 tcpcheck->string_len = strlen(args[2]);
4453 tcpcheck->string = strdup(args[2]);
4454 tcpcheck->expect_regex = NULL;
4455
4456 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4457 }
4458 }
4459 else if (strcmp(args[1], "send-binary") == 0) {
4460 if (! *(args[2]) ) {
4461 /* SEND binary string expected */
4462 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4463 file, linenum, args[0], args[1], args[2]);
4464 err_code |= ERR_ALERT | ERR_FATAL;
4465 goto out;
4466 } else {
4467 struct tcpcheck_rule *tcpcheck;
4468 char *err = NULL;
4469
4470 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4471
4472 tcpcheck->action = TCPCHK_ACT_SEND;
4473 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4474 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4475 file, linenum, args[0], args[1], args[2], err);
4476 err_code |= ERR_ALERT | ERR_FATAL;
4477 goto out;
4478 }
4479 tcpcheck->expect_regex = NULL;
4480
4481 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4482 }
4483 }
4484 else if (strcmp(args[1], "expect") == 0) {
4485 const char *ptr_arg;
4486 int cur_arg;
4487 int inverse = 0;
4488
4489 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4490 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
4494
4495 cur_arg = 2;
4496 /* consider exclamation marks, sole or at the beginning of a word */
4497 while (*(ptr_arg = args[cur_arg])) {
4498 while (*ptr_arg == '!') {
4499 inverse = !inverse;
4500 ptr_arg++;
4501 }
4502 if (*ptr_arg)
4503 break;
4504 cur_arg++;
4505 }
4506 /* now ptr_arg points to the beginning of a word past any possible
4507 * exclamation mark, and cur_arg is the argument which holds this word.
4508 */
4509 if (strcmp(ptr_arg, "binary") == 0) {
4510 if (!*(args[cur_arg + 1])) {
4511 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4512 file, linenum, args[0], args[1], ptr_arg);
4513 err_code |= ERR_ALERT | ERR_FATAL;
4514 goto out;
4515 }
4516 struct tcpcheck_rule *tcpcheck;
4517 char *err = NULL;
4518
4519 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4520
4521 tcpcheck->action = TCPCHK_ACT_EXPECT;
4522 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4523 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4524 file, linenum, args[0], args[1], args[2], err);
4525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
4527 }
4528 tcpcheck->expect_regex = NULL;
4529 tcpcheck->inverse = inverse;
4530
4531 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4532 }
4533 else if (strcmp(ptr_arg, "string") == 0) {
4534 if (!*(args[cur_arg + 1])) {
4535 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4536 file, linenum, args[0], args[1], ptr_arg);
4537 err_code |= ERR_ALERT | ERR_FATAL;
4538 goto out;
4539 }
4540 struct tcpcheck_rule *tcpcheck;
4541
4542 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4543
4544 tcpcheck->action = TCPCHK_ACT_EXPECT;
4545 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4546 tcpcheck->string = strdup(args[cur_arg + 1]);
4547 tcpcheck->expect_regex = NULL;
4548 tcpcheck->inverse = inverse;
4549
4550 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4551 }
4552 else if (strcmp(ptr_arg, "rstring") == 0) {
4553 if (!*(args[cur_arg + 1])) {
4554 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4555 file, linenum, args[0], args[1], ptr_arg);
4556 err_code |= ERR_ALERT | ERR_FATAL;
4557 goto out;
4558 }
4559 struct tcpcheck_rule *tcpcheck;
4560
4561 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4562
4563 tcpcheck->action = TCPCHK_ACT_EXPECT;
4564 tcpcheck->string_len = 0;
4565 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004566 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4567 error = NULL;
4568 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4569 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4570 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4571 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004572 err_code |= ERR_ALERT | ERR_FATAL;
4573 goto out;
4574 }
4575 tcpcheck->inverse = inverse;
4576
4577 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4578 }
4579 else {
4580 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4581 file, linenum, args[0], args[1], ptr_arg);
4582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
4584 }
4585 }
4586 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004587 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004588 err_code |= ERR_ALERT | ERR_FATAL;
4589 goto out;
4590 }
4591 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004592 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004593 if (curproxy == &defproxy) {
4594 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004595 err_code |= ERR_ALERT | ERR_FATAL;
4596 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004597 }
4598
Willy Tarreaub80c2302007-11-30 20:51:32 +01004599 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004600 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004601
4602 if (strcmp(args[1], "fail") == 0) {
4603 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004604 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004605 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4606 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004607 err_code |= ERR_ALERT | ERR_FATAL;
4608 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004609 }
4610
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004611 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4612 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4613 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004616 }
4617 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4618 }
4619 else {
4620 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004623 }
4624 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004625#ifdef TPROXY
4626 else if (!strcmp(args[0], "transparent")) {
4627 /* enable transparent proxy connections */
4628 curproxy->options |= PR_O_TRANSP;
4629 }
4630#endif
4631 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004632 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004634
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 if (*(args[1]) == 0) {
4636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 }
4640 curproxy->maxconn = atol(args[1]);
4641 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004642 else if (!strcmp(args[0], "backlog")) { /* backlog */
4643 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004644 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004645
4646 if (*(args[1]) == 0) {
4647 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004650 }
4651 curproxy->backlog = atol(args[1]);
4652 }
Willy Tarreau86034312006-12-29 00:10:33 +01004653 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004654 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004655 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004656
Willy Tarreau86034312006-12-29 00:10:33 +01004657 if (*(args[1]) == 0) {
4658 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004661 }
4662 curproxy->fullconn = atol(args[1]);
4663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004664 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4665 if (*(args[1]) == 0) {
4666 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004667 err_code |= ERR_ALERT | ERR_FATAL;
4668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004669 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004670 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4671 if (err) {
4672 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4673 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004674 err_code |= ERR_ALERT | ERR_FATAL;
4675 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004676 }
4677 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 }
4679 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004680 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004681 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004682 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004683
Willy Tarreaubaaee002006-06-26 02:48:02 +02004684 if (curproxy == &defproxy) {
4685 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004689 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004690 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004691
Willy Tarreau902636f2013-03-10 19:44:48 +01004692 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004693 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004694 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004695 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004696 goto out;
4697 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004698
4699 proto = protocol_by_family(sk->ss_family);
4700 if (!proto || !proto->connect) {
4701 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4702 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004703 err_code |= ERR_ALERT | ERR_FATAL;
4704 goto out;
4705 }
4706
4707 if (port1 != port2) {
4708 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4709 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004710 err_code |= ERR_ALERT | ERR_FATAL;
4711 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004712 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004713
4714 if (!port1) {
4715 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4716 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004717 err_code |= ERR_ALERT | ERR_FATAL;
4718 goto out;
4719 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004720
Willy Tarreaud5191e72010-02-09 20:50:45 +01004721 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004722 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004723 }
4724 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004726 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004727
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004728 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4729 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_ALERT | ERR_FATAL;
4731 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004732 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004733 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004734 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004735 /**
4736 * The syntax for hash-type config element is
4737 * hash-type {map-based|consistent} [[<algo>] avalanche]
4738 *
4739 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4740 */
4741 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004742
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4744 err_code |= ERR_WARN;
4745
4746 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004747 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4748 }
4749 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004750 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4751 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004752 else if (strcmp(args[1], "avalanche") == 0) {
4753 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]);
4754 err_code |= ERR_ALERT | ERR_FATAL;
4755 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004756 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004757 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004758 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761 }
Bhaskar98634f02013-10-29 23:30:51 -04004762
4763 /* set the hash function to use */
4764 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004765 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004766 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004767
4768 /* if consistent with no argument, then avalanche modifier is also applied */
4769 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4770 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004771 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004772 /* set the hash function */
4773 if (!strcmp(args[2], "sdbm")) {
4774 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4775 }
4776 else if (!strcmp(args[2], "djb2")) {
4777 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004778 } else if (!strcmp(args[2], "wt6")) {
4779 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004780 }
4781 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004782 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 -05004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
4785 }
4786
4787 /* set the hash modifier */
4788 if (!strcmp(args[3], "avalanche")) {
4789 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4790 }
4791 else if (*args[3]) {
4792 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4793 err_code |= ERR_ALERT | ERR_FATAL;
4794 goto out;
4795 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004796 }
William Lallemanda73203e2012-03-12 12:48:57 +01004797 }
William Lallemanda73203e2012-03-12 12:48:57 +01004798 else if (strcmp(args[0], "unique-id-format") == 0) {
4799 if (!*(args[1])) {
4800 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4801 err_code |= ERR_ALERT | ERR_FATAL;
4802 goto out;
4803 }
William Lallemand3203ff42012-11-11 17:30:56 +01004804 if (*(args[2])) {
4805 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4806 err_code |= ERR_ALERT | ERR_FATAL;
4807 goto out;
4808 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004809 free(curproxy->conf.uniqueid_format_string);
4810 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004811
Willy Tarreau62a61232013-04-12 18:13:46 +02004812 free(curproxy->conf.uif_file);
4813 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4814 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004815 }
William Lallemanda73203e2012-03-12 12:48:57 +01004816
4817 else if (strcmp(args[0], "unique-id-header") == 0) {
4818 if (!*(args[1])) {
4819 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
4822 }
4823 free(curproxy->header_unique_id);
4824 curproxy->header_unique_id = strdup(args[1]);
4825 }
4826
William Lallemand723b73a2012-02-08 16:37:49 +01004827 else if (strcmp(args[0], "log-format") == 0) {
4828 if (!*(args[1])) {
4829 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4830 err_code |= ERR_ALERT | ERR_FATAL;
4831 goto out;
4832 }
William Lallemand3203ff42012-11-11 17:30:56 +01004833 if (*(args[2])) {
4834 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4835 err_code |= ERR_ALERT | ERR_FATAL;
4836 goto out;
4837 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004838
Willy Tarreau62a61232013-04-12 18:13:46 +02004839 if (curproxy->conf.logformat_string != default_http_log_format &&
4840 curproxy->conf.logformat_string != default_tcp_log_format &&
4841 curproxy->conf.logformat_string != clf_http_log_format)
4842 free(curproxy->conf.logformat_string);
4843 curproxy->conf.logformat_string = strdup(args[1]);
4844
4845 free(curproxy->conf.lfs_file);
4846 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4847 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004848
4849 /* get a chance to improve log-format error reporting by
4850 * reporting the correct line-number when possible.
4851 */
4852 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4853 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4854 file, linenum, curproxy->id);
4855 err_code |= ERR_WARN;
4856 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004857 }
William Lallemand723b73a2012-02-08 16:37:49 +01004858
William Lallemand0f99e342011-10-12 17:50:54 +02004859 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4860 /* delete previous herited or defined syslog servers */
4861 struct logsrv *back;
4862
4863 if (*(args[1]) != 0) {
4864 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4865 err_code |= ERR_ALERT | ERR_FATAL;
4866 goto out;
4867 }
4868
William Lallemand723b73a2012-02-08 16:37:49 +01004869 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4870 LIST_DEL(&tmplogsrv->list);
4871 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004872 }
4873 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004874 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004875 struct logsrv *logsrv;
4876
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004878 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004879 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004880 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004881 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004882 LIST_INIT(&node->list);
4883 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4884 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004885 }
4886 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004887 struct sockaddr_storage *sk;
4888 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004889 int arg = 0;
4890 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004891
4892 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004893
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004894 /* just after the address, a length may be specified */
4895 if (strcmp(args[arg+2], "len") == 0) {
4896 len = atoi(args[arg+3]);
4897 if (len < 80 || len > 65535) {
4898 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4899 file, linenum, args[arg+3]);
4900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
4902 }
4903 logsrv->maxlen = len;
4904
4905 /* skip these two args */
4906 arg += 2;
4907 }
4908 else
4909 logsrv->maxlen = MAX_SYSLOG_LEN;
4910
4911 if (logsrv->maxlen > global.max_syslog_len) {
4912 global.max_syslog_len = logsrv->maxlen;
4913 logline = realloc(logline, global.max_syslog_len + 1);
4914 }
4915
4916 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004917 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004918 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004919 err_code |= ERR_ALERT | ERR_FATAL;
4920 goto out;
4921
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 }
4923
William Lallemand0f99e342011-10-12 17:50:54 +02004924 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004925 if (*(args[arg+3])) {
4926 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004927 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004928 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004929 err_code |= ERR_ALERT | ERR_FATAL;
4930 goto out;
4931
Willy Tarreaubaaee002006-06-26 02:48:02 +02004932 }
4933 }
4934
William Lallemand0f99e342011-10-12 17:50:54 +02004935 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004936 if (*(args[arg+4])) {
4937 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004938 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004939 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004940 err_code |= ERR_ALERT | ERR_FATAL;
4941 goto out;
4942
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004943 }
4944 }
4945
Willy Tarreau902636f2013-03-10 19:44:48 +01004946 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004947 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004948 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004949 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004950 goto out;
4951 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004952
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004953 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004954
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004955 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004956 if (port1 != port2) {
4957 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4958 file, linenum, args[0], args[1]);
4959 err_code |= ERR_ALERT | ERR_FATAL;
4960 goto out;
4961 }
4962
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004963 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004964 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
William Lallemand0f99e342011-10-12 17:50:54 +02004966
4967 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 }
4969 else {
4970 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4971 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
4975 }
4976 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004977 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004978 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004979 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004980 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004981
Willy Tarreau977b8e42006-12-29 14:19:17 +01004982 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004983 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004984
Willy Tarreaubaaee002006-06-26 02:48:02 +02004985 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004986 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4987 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004990 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004991
4992 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004993 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4994 free(curproxy->conn_src.iface_name);
4995 curproxy->conn_src.iface_name = NULL;
4996 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004997
Willy Tarreau902636f2013-03-10 19:44:48 +01004998 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004999 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005000 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005001 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005002 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005003 goto out;
5004 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005005
5006 proto = protocol_by_family(sk->ss_family);
5007 if (!proto || !proto->connect) {
5008 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005009 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
5012 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005013
5014 if (port1 != port2) {
5015 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5016 file, linenum, args[0], args[1]);
5017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
5019 }
5020
Willy Tarreauef9a3602012-12-08 22:29:20 +01005021 curproxy->conn_src.source_addr = *sk;
5022 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005023
5024 cur_arg = 2;
5025 while (*(args[cur_arg])) {
5026 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005027#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5028#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005029 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005030 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5031 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005032 err_code |= ERR_ALERT | ERR_FATAL;
5033 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005034 }
5035#endif
5036 if (!*args[cur_arg + 1]) {
5037 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5038 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005039 err_code |= ERR_ALERT | ERR_FATAL;
5040 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005041 }
5042
5043 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005044 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5045 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005046 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005047 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5048 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005049 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5050 char *name, *end;
5051
5052 name = args[cur_arg+1] + 7;
5053 while (isspace(*name))
5054 name++;
5055
5056 end = name;
5057 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5058 end++;
5059
Willy Tarreauef9a3602012-12-08 22:29:20 +01005060 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5061 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5062 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5063 curproxy->conn_src.bind_hdr_len = end - name;
5064 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5065 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5066 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005067
5068 /* now look for an occurrence number */
5069 while (isspace(*end))
5070 end++;
5071 if (*end == ',') {
5072 end++;
5073 name = end;
5074 if (*end == '-')
5075 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005076 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005077 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005078 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005079 }
5080
Willy Tarreauef9a3602012-12-08 22:29:20 +01005081 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005082 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5083 " occurrences values smaller than %d.\n",
5084 file, linenum, MAX_HDR_HISTORY);
5085 err_code |= ERR_ALERT | ERR_FATAL;
5086 goto out;
5087 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005088 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005089 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005090
Willy Tarreau902636f2013-03-10 19:44:48 +01005091 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005092 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005093 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005094 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005095 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005096 goto out;
5097 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005098
5099 proto = protocol_by_family(sk->ss_family);
5100 if (!proto || !proto->connect) {
5101 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5102 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005103 err_code |= ERR_ALERT | ERR_FATAL;
5104 goto out;
5105 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005106
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005107 if (port1 != port2) {
5108 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5109 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
5112 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005113 curproxy->conn_src.tproxy_addr = *sk;
5114 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005115 }
5116 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005117#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005118 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005119#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005120#else /* no TPROXY support */
5121 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005122 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005125#endif
5126 cur_arg += 2;
5127 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005128 }
5129
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005130 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5131#ifdef SO_BINDTODEVICE
5132 if (!*args[cur_arg + 1]) {
5133 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5134 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005137 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005138 free(curproxy->conn_src.iface_name);
5139 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5140 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005141 global.last_checks |= LSTCHK_NETADM;
5142#else
5143 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5144 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005147#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005148 cur_arg += 2;
5149 continue;
5150 }
5151 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005152 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005153 err_code |= ERR_ALERT | ERR_FATAL;
5154 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005155 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005156 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005157 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5158 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5159 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005162 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005163 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005164 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005165 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5166 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170
5171 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005172 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005173 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005174 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005175 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 }
5177 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005179 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005180 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005181 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
5184 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005186 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005187 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005188 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005189 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005190 }
5191 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005193 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005194 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005195 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005197 }
5198 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005200 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005201 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005202 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005203 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005204 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005205 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005207 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005208 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005209 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005210 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005211 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005212 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005213 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005214 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005215 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005216 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005217 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005218
5219 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5220 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 +01005221 }
5222 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005223 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005224 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005225 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005226 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005227 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005228
5229 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5230 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 +01005231 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005232 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005233 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005234 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5235 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005236 err_code |= ERR_ALERT | ERR_FATAL;
5237 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239
5240 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005241 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005242 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005244 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005245 }
5246 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005247 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005248 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005249 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005250 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005252 }
5253 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005255 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005256 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005257 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005258 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 }
5260 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005262 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005263 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005264 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
5267 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005269 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005270 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005271 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005274 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005276 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005277 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005278 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005279 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005281 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005282 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005283
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 if (curproxy == &defproxy) {
5285 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005289 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005290 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 if (*(args[1]) == 0) {
5293 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005297
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005298 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005299 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5300 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5301 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005305 err_code |= warnif_cond_conflicts(cond,
5306 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5307 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005308 }
5309 else if (*args[2]) {
5310 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5311 file, linenum, args[0], args[2]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005316 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005317 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005318 wl->s = strdup(args[1]);
5319 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005320 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005321 }
5322 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005323 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005324 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5325 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005329
Willy Tarreauade5ec42010-01-28 19:33:49 +01005330 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005331 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005332 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005333 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005335 }
5336 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005337 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005338 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005339 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005340 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005342 }
5343 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005344 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005345 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005346 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005347 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005348 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005349 }
5350 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005351 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005352 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5353 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 }
5357
Willy Tarreauade5ec42010-01-28 19:33:49 +01005358 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005359 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005360 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005361 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
5364 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005365 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005366 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005367 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005368 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005370 }
5371 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005372 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005373 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005374 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005375 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005377 }
5378 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005379 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005380
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 if (curproxy == &defproxy) {
5382 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005386 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005388
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 if (*(args[1]) == 0) {
5390 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 }
5394
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005395 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005396 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5397 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5398 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005402 err_code |= warnif_cond_conflicts(cond,
5403 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5404 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005405 }
5406 else if (*args[2]) {
5407 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5408 file, linenum, args[0], args[2]);
5409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
5412
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005413 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005414 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005415 wl->s = strdup(args[1]);
5416 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005417 }
5418 else if (!strcmp(args[0], "errorloc") ||
5419 !strcmp(args[0], "errorloc302") ||
5420 !strcmp(args[0], "errorloc303")) { /* error location */
5421 int errnum, errlen;
5422 char *err;
5423
Willy Tarreau977b8e42006-12-29 14:19:17 +01005424 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005425 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005426
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005428 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 }
5432
5433 errnum = atol(args[1]);
5434 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005435 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5436 err = malloc(errlen);
5437 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005438 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005439 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5440 err = malloc(errlen);
5441 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 }
5443
Willy Tarreau0f772532006-12-23 20:51:41 +01005444 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5445 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005446 chunk_destroy(&curproxy->errmsg[rc]);
5447 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005448 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005449 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005450 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005451
5452 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005453 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
5454 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 free(err);
5456 }
5457 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005458 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5459 int errnum, errlen, fd;
5460 char *err;
5461 struct stat stat;
5462
5463 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005464 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005465
5466 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005467 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005468 err_code |= ERR_ALERT | ERR_FATAL;
5469 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005470 }
5471
5472 fd = open(args[2], O_RDONLY);
5473 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5474 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5475 file, linenum, args[2], args[1]);
5476 if (fd >= 0)
5477 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005478 err_code |= ERR_ALERT | ERR_FATAL;
5479 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005480 }
5481
Willy Tarreau27a674e2009-08-17 07:23:33 +02005482 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005483 errlen = stat.st_size;
5484 } else {
5485 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005486 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005487 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005488 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005489 }
5490
5491 err = malloc(errlen); /* malloc() must succeed during parsing */
5492 errnum = read(fd, err, errlen);
5493 if (errnum != errlen) {
5494 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5495 file, linenum, args[2], args[1]);
5496 close(fd);
5497 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005500 }
5501 close(fd);
5502
5503 errnum = atol(args[1]);
5504 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5505 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005506 chunk_destroy(&curproxy->errmsg[rc]);
5507 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005508 break;
5509 }
5510 }
5511
5512 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005513 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
5514 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005515 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005516 free(err);
5517 }
5518 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005519 else if (!strcmp(args[0], "compression")) {
5520 struct comp *comp;
5521 if (curproxy->comp == NULL) {
5522 comp = calloc(1, sizeof(struct comp));
5523 curproxy->comp = comp;
5524 } else {
5525 comp = curproxy->comp;
5526 }
5527
5528 if (!strcmp(args[1], "algo")) {
5529 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005530 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005531
William Lallemand82fe75c2012-10-23 10:25:10 +02005532 cur_arg = 2;
5533 if (!*args[cur_arg]) {
5534 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5535 file, linenum, args[0]);
5536 err_code |= ERR_ALERT | ERR_FATAL;
5537 goto out;
5538 }
5539 while (*(args[cur_arg])) {
5540 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5541 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5542 file, linenum, args[0], args[cur_arg]);
5543 err_code |= ERR_ALERT | ERR_FATAL;
5544 goto out;
5545 }
William Lallemand552df672012-11-07 13:21:47 +01005546 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5547 curproxy->comp->algos->end(&ctx);
5548 } else {
5549 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5550 file, linenum, args[0], args[cur_arg]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005554 cur_arg ++;
5555 continue;
5556 }
5557 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005558 else if (!strcmp(args[1], "offload")) {
5559 comp->offload = 1;
5560 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005561 else if (!strcmp(args[1], "type")) {
5562 int cur_arg;
5563 cur_arg = 2;
5564 if (!*args[cur_arg]) {
5565 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5566 file, linenum, args[0]);
5567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
5569 }
5570 while (*(args[cur_arg])) {
5571 comp_append_type(comp, args[cur_arg]);
5572 cur_arg ++;
5573 continue;
5574 }
5575 }
5576 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005577 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005578 file, linenum, args[0]);
5579 err_code |= ERR_ALERT | ERR_FATAL;
5580 goto out;
5581 }
5582 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005584 struct cfg_kw_list *kwl;
5585 int index;
5586
5587 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5588 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5589 if (kwl->kw[index].section != CFG_LISTEN)
5590 continue;
5591 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5592 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005593 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005594 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005595 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_ALERT | ERR_FATAL;
5597 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005598 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005599 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005600 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005601 err_code |= ERR_WARN;
5602 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005603 }
Willy Tarreau93893792009-07-23 13:19:11 +02005604 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005605 }
5606 }
5607 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005608
Willy Tarreau6daf3432008-01-22 16:44:08 +01005609 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005612 }
Willy Tarreau93893792009-07-23 13:19:11 +02005613 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005614 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005615 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616}
5617
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005618int
5619cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5620{
5621
5622 int err_code = 0;
5623 const char *err;
5624
5625 if (!strcmp(args[0], "userlist")) { /* new userlist */
5626 struct userlist *newul;
5627
5628 if (!*args[1]) {
5629 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5630 file, linenum, args[0]);
5631 err_code |= ERR_ALERT | ERR_FATAL;
5632 goto out;
5633 }
5634
5635 err = invalid_char(args[1]);
5636 if (err) {
5637 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5638 file, linenum, *err, args[0], args[1]);
5639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
5642
5643 for (newul = userlist; newul; newul = newul->next)
5644 if (!strcmp(newul->name, args[1])) {
5645 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5646 file, linenum, args[1]);
5647 err_code |= ERR_WARN;
5648 goto out;
5649 }
5650
5651 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5652 if (!newul) {
5653 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5654 err_code |= ERR_ALERT | ERR_ABORT;
5655 goto out;
5656 }
5657
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005658 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005659 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005660 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5661 err_code |= ERR_ALERT | ERR_ABORT;
5662 goto out;
5663 }
5664
5665 newul->next = userlist;
5666 userlist = newul;
5667
5668 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005669 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005670 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005671 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005672
5673 if (!*args[1]) {
5674 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5675 file, linenum, args[0]);
5676 err_code |= ERR_ALERT | ERR_FATAL;
5677 goto out;
5678 }
5679
5680 err = invalid_char(args[1]);
5681 if (err) {
5682 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5683 file, linenum, *err, args[0], args[1]);
5684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
5687
William Lallemandfaf33152015-05-28 18:03:51 +02005688 if (!userlist)
5689 goto out;
5690
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005691 for (ag = userlist->groups; ag; ag = ag->next)
5692 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005693 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5694 file, linenum, args[1], userlist->name);
5695 err_code |= ERR_ALERT;
5696 goto out;
5697 }
5698
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005699 ag = calloc(1, sizeof(*ag));
5700 if (!ag) {
5701 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5702 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005703 goto out;
5704 }
5705
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005706 ag->name = strdup(args[1]);
5707 if (!ag) {
5708 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5709 err_code |= ERR_ALERT | ERR_ABORT;
5710 goto out;
5711 }
5712
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005713 cur_arg = 2;
5714
5715 while (*args[cur_arg]) {
5716 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005717 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005718 cur_arg += 2;
5719 continue;
5720 } else {
5721 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5722 file, linenum, args[0]);
5723 err_code |= ERR_ALERT | ERR_FATAL;
5724 goto out;
5725 }
5726 }
5727
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005728 ag->next = userlist->groups;
5729 userlist->groups = ag;
5730
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005731 } else if (!strcmp(args[0], "user")) { /* new user */
5732 struct auth_users *newuser;
5733 int cur_arg;
5734
5735 if (!*args[1]) {
5736 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5737 file, linenum, args[0]);
5738 err_code |= ERR_ALERT | ERR_FATAL;
5739 goto out;
5740 }
William Lallemandfaf33152015-05-28 18:03:51 +02005741 if (!userlist)
5742 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005743
5744 for (newuser = userlist->users; newuser; newuser = newuser->next)
5745 if (!strcmp(newuser->user, args[1])) {
5746 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5747 file, linenum, args[1], userlist->name);
5748 err_code |= ERR_ALERT;
5749 goto out;
5750 }
5751
5752 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5753 if (!newuser) {
5754 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5755 err_code |= ERR_ALERT | ERR_ABORT;
5756 goto out;
5757 }
5758
5759 newuser->user = strdup(args[1]);
5760
5761 newuser->next = userlist->users;
5762 userlist->users = newuser;
5763
5764 cur_arg = 2;
5765
5766 while (*args[cur_arg]) {
5767 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005768#ifdef CONFIG_HAP_CRYPT
5769 if (!crypt("", args[cur_arg + 1])) {
5770 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5771 file, linenum, newuser->user);
5772 err_code |= ERR_ALERT | ERR_FATAL;
5773 goto out;
5774 }
5775#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005776 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5777 file, linenum);
5778 err_code |= ERR_ALERT;
5779#endif
5780 newuser->pass = strdup(args[cur_arg + 1]);
5781 cur_arg += 2;
5782 continue;
5783 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5784 newuser->pass = strdup(args[cur_arg + 1]);
5785 newuser->flags |= AU_O_INSECURE;
5786 cur_arg += 2;
5787 continue;
5788 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005789 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005790 cur_arg += 2;
5791 continue;
5792 } else {
5793 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5794 file, linenum, args[0]);
5795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
5797 }
5798 }
5799 } else {
5800 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5801 err_code |= ERR_ALERT | ERR_FATAL;
5802 }
5803
5804out:
5805 return err_code;
5806}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005807
5808/*
5809 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005810 * Returns the error code, 0 if OK, or any combination of :
5811 * - ERR_ABORT: must abort ASAP
5812 * - ERR_FATAL: we can continue parsing but not start the service
5813 * - ERR_WARN: a warning has been emitted
5814 * - ERR_ALERT: an alert has been emitted
5815 * Only the two first ones can stop processing, the two others are just
5816 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005817 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005818int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005820 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 FILE *f;
5822 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005823 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005824 struct cfg_section *cs = NULL;
5825 struct cfg_section *ics;
5826
5827 /* Register internal sections */
5828 if (!cfg_register_section("listen", cfg_parse_listen) ||
5829 !cfg_register_section("frontend", cfg_parse_listen) ||
5830 !cfg_register_section("backend", cfg_parse_listen) ||
5831 !cfg_register_section("ruleset", cfg_parse_listen) ||
5832 !cfg_register_section("defaults", cfg_parse_listen) ||
5833 !cfg_register_section("global", cfg_parse_global) ||
5834 !cfg_register_section("userlist", cfg_parse_users) ||
5835 !cfg_register_section("peers", cfg_parse_peers))
5836 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 if ((f=fopen(file,"r")) == NULL)
5839 return -1;
5840
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005841 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005842 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005843 char *end;
5844 char *args[MAX_LINE_ARGS + 1];
5845 char *line = thisline;
5846
Willy Tarreaubaaee002006-06-26 02:48:02 +02005847 linenum++;
5848
5849 end = line + strlen(line);
5850
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005851 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5852 /* Check if we reached the limit and the last char is not \n.
5853 * Watch out for the last line without the terminating '\n'!
5854 */
5855 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005856 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005857 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005858 }
5859
Willy Tarreaubaaee002006-06-26 02:48:02 +02005860 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005861 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 line++;
5863
5864 arg = 0;
5865 args[arg] = line;
5866
5867 while (*line && arg < MAX_LINE_ARGS) {
5868 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5869 * C equivalent value. Other combinations left unchanged (eg: \1).
5870 */
5871 if (*line == '\\') {
5872 int skip = 0;
5873 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5874 *line = line[1];
5875 skip = 1;
5876 }
5877 else if (line[1] == 'r') {
5878 *line = '\r';
5879 skip = 1;
5880 }
5881 else if (line[1] == 'n') {
5882 *line = '\n';
5883 skip = 1;
5884 }
5885 else if (line[1] == 't') {
5886 *line = '\t';
5887 skip = 1;
5888 }
5889 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005890 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005891 unsigned char hex1, hex2;
5892 hex1 = toupper(line[2]) - '0';
5893 hex2 = toupper(line[3]) - '0';
5894 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5895 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5896 *line = (hex1<<4) + hex2;
5897 skip = 3;
5898 }
5899 else {
5900 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005901 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005902 }
5903 }
5904 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005905 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 end -= skip;
5907 }
5908 line++;
5909 }
5910 else if (*line == '#' || *line == '\n' || *line == '\r') {
5911 /* end of string, end of loop */
5912 *line = 0;
5913 break;
5914 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005915 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005916 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005917 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005918 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 line++;
5920 args[++arg] = line;
5921 }
5922 else {
5923 line++;
5924 }
5925 }
5926
5927 /* empty line */
5928 if (!**args)
5929 continue;
5930
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005931 if (*line) {
5932 /* we had to stop due to too many args.
5933 * Let's terminate the string, print the offending part then cut the
5934 * last arg.
5935 */
5936 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5937 line++;
5938 *line = '\0';
5939
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005940 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005941 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005942 err_code |= ERR_ALERT | ERR_FATAL;
5943 args[arg] = line;
5944 }
5945
Willy Tarreau540abe42007-05-02 20:50:16 +02005946 /* zero out remaining args and ensure that at least one entry
5947 * is zeroed out.
5948 */
5949 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005950 args[arg] = line;
5951 }
5952
Willy Tarreau3842f002009-06-14 11:39:52 +02005953 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005954 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005955 char *tmp;
5956
Willy Tarreau3842f002009-06-14 11:39:52 +02005957 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005958 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005959 for (arg=0; *args[arg+1]; arg++)
5960 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005961 *tmp = '\0'; // fix the next arg to \0
5962 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005963 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005964 else if (!strcmp(args[0], "default")) {
5965 kwm = KWM_DEF;
5966 for (arg=0; *args[arg+1]; arg++)
5967 args[arg] = args[arg+1]; // shift args after inversion
5968 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005969
William Lallemand0f99e342011-10-12 17:50:54 +02005970 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5971 strcmp(args[0], "log") != 0) {
5972 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005973 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005974 }
5975
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005976 /* detect section start */
5977 list_for_each_entry(ics, &sections, list) {
5978 if (strcmp(args[0], ics->section_name) == 0) {
5979 cursection = ics->section_name;
5980 cs = ics;
5981 break;
5982 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005983 }
5984
Willy Tarreaubaaee002006-06-26 02:48:02 +02005985 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005986 if (cs)
5987 err_code |= cs->section_parser(file, linenum, args, kwm);
5988 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005989 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005990 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005992
5993 if (err_code & ERR_ABORT)
5994 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005996 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005998 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005999}
6000
Willy Tarreau5436afc2014-09-16 12:17:36 +02006001/* This function propagates processes from frontend <from> to backend <to> so
6002 * that it is always guaranteed that a backend pointed to by a frontend is
6003 * bound to all of its processes. After that, if the target is a "listen"
6004 * instance, the function recursively descends the target's own targets along
6005 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6006 * checked first to ensure that <to> is already bound to all processes of
6007 * <from>, there is no risk of looping and we ensure to follow the shortest
6008 * path to the destination.
6009 *
6010 * It is possible to set <to> to NULL for the first call so that the function
6011 * takes care of visiting the initial frontend in <from>.
6012 *
6013 * It is important to note that the function relies on the fact that all names
6014 * have already been resolved.
6015 */
6016void propagate_processes(struct proxy *from, struct proxy *to)
6017{
6018 struct switching_rule *rule;
6019 struct hdr_exp *exp;
6020
6021 if (to) {
6022 /* check whether we need to go down */
6023 if (from->bind_proc &&
6024 (from->bind_proc & to->bind_proc) == from->bind_proc)
6025 return;
6026
6027 if (!from->bind_proc && !to->bind_proc)
6028 return;
6029
6030 to->bind_proc = from->bind_proc ?
6031 (to->bind_proc | from->bind_proc) : 0;
6032
6033 /* now propagate down */
6034 from = to;
6035 }
6036
Willy Tarreau7110f382014-12-18 13:56:26 +01006037 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006038 return;
6039
Willy Tarreaued061c02014-12-18 14:00:43 +01006040 if (from->state == PR_STSTOPPED)
6041 return;
6042
Willy Tarreau5436afc2014-09-16 12:17:36 +02006043 /* default_backend */
6044 if (from->defbe.be)
6045 propagate_processes(from, from->defbe.be);
6046
6047 /* use_backend */
6048 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006049 if (rule->dynamic)
6050 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006051 to = rule->be.backend;
6052 propagate_processes(from, to);
6053 }
6054
6055 /* reqsetbe */
6056 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6057 if (exp->action != ACT_SETBE)
6058 continue;
6059 to = (struct proxy *)exp->replace;
6060 propagate_processes(from, to);
6061 }
6062}
6063
Willy Tarreaubb925012009-07-23 13:36:36 +02006064/*
6065 * Returns the error code, 0 if OK, or any combination of :
6066 * - ERR_ABORT: must abort ASAP
6067 * - ERR_FATAL: we can continue parsing but not start the service
6068 * - ERR_WARN: a warning has been emitted
6069 * - ERR_ALERT: an alert has been emitted
6070 * Only the two first ones can stop processing, the two others are just
6071 * indicators.
6072 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006073int check_config_validity()
6074{
6075 int cfgerr = 0;
6076 struct proxy *curproxy = NULL;
6077 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006078 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006079 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006080 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006082 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006083 /*
6084 * Now, check for the integrity of all that we have collected.
6085 */
6086
6087 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006088 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006089
Willy Tarreau193b8c62012-11-22 00:17:38 +01006090 if (!global.tune.max_http_hdr)
6091 global.tune.max_http_hdr = MAX_HTTP_HDR;
6092
6093 if (!global.tune.cookie_len)
6094 global.tune.cookie_len = CAPTURE_LEN;
6095
6096 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6097
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006098 /* Post initialisation of the users and groups lists. */
6099 err_code = userlist_postinit();
6100 if (err_code != ERR_NONE)
6101 goto out;
6102
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006103 /* first, we will invert the proxy list order */
6104 curproxy = NULL;
6105 while (proxy) {
6106 struct proxy *next;
6107
6108 next = proxy->next;
6109 proxy->next = curproxy;
6110 curproxy = proxy;
6111 if (!next)
6112 break;
6113 proxy = next;
6114 }
6115
Willy Tarreau91b00c22014-09-16 13:41:21 +02006116 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006117 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006118 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006119 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006120 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006121 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006122 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006123
Willy Tarreau050536d2012-10-04 08:47:34 +02006124 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006125 /* proxy ID not set, use automatic numbering with first
6126 * spare entry starting with next_pxid.
6127 */
6128 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6129 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6130 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006131 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006132 next_pxid++;
6133
Willy Tarreau55ea7572007-06-17 19:56:27 +02006134
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006136 /* ensure we don't keep listeners uselessly bound */
6137 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006138 free((void *)curproxy->table.peers.name);
6139 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006140 continue;
6141 }
6142
Willy Tarreau102df612014-05-07 23:56:38 +02006143 /* Check multi-process mode compatibility for the current proxy */
6144
6145 if (curproxy->bind_proc) {
6146 /* an explicit bind-process was specified, let's check how many
6147 * processes remain.
6148 */
David Carlier6de4c2f2015-07-02 07:00:17 +00006149 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02006150
6151 curproxy->bind_proc &= nbits(global.nbproc);
6152 if (!curproxy->bind_proc && nbproc == 1) {
6153 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);
6154 curproxy->bind_proc = 1;
6155 }
6156 else if (!curproxy->bind_proc && nbproc > 1) {
6157 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);
6158 curproxy->bind_proc = 0;
6159 }
6160 }
6161
Willy Tarreau3d209582014-05-09 17:06:11 +02006162 /* check and reduce the bind-proc of each listener */
6163 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6164 unsigned long mask;
6165
6166 if (!bind_conf->bind_proc)
6167 continue;
6168
6169 mask = nbits(global.nbproc);
6170 if (curproxy->bind_proc)
6171 mask &= curproxy->bind_proc;
6172 /* mask cannot be null here thanks to the previous checks */
6173
David Carlier6de4c2f2015-07-02 07:00:17 +00006174 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02006175 bind_conf->bind_proc &= mask;
6176
6177 if (!bind_conf->bind_proc && nbproc == 1) {
6178 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",
6179 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6180 bind_conf->bind_proc = mask & ~(mask - 1);
6181 }
6182 else if (!bind_conf->bind_proc && nbproc > 1) {
6183 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",
6184 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6185 bind_conf->bind_proc = 0;
6186 }
6187 }
6188
Willy Tarreauff01a212009-03-15 13:46:16 +01006189 switch (curproxy->mode) {
6190 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006191 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006192 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006193 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6194 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006195 cfgerr++;
6196 }
6197
6198 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006199 Warning("config : servers will be ignored for %s '%s'.\n",
6200 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006201 break;
6202
6203 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006204 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006205 break;
6206
6207 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006208 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006209 break;
6210 }
6211
Willy Tarreauc7c1e552015-08-11 11:36:45 +02006212 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
6213 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
6214 proxy_type_str(curproxy), curproxy->id);
6215 err_code |= ERR_WARN;
6216 }
6217
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006218 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006219 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006220 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006221 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6222 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006223 cfgerr++;
6224 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006225#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006226 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006227 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6228 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006229 cfgerr++;
6230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006231#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006232 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006233 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6234 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006235 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006236 }
6237 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006238 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006239 /* If no LB algo is set in a backend, and we're not in
6240 * transparent mode, dispatch mode nor proxy mode, we
6241 * want to use balance roundrobin by default.
6242 */
6243 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6244 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006245 }
6246 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006247
Willy Tarreau1620ec32011-08-06 17:05:02 +02006248 if (curproxy->options & PR_O_DISPATCH)
6249 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6250 else if (curproxy->options & PR_O_HTTP_PROXY)
6251 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6252 else if (curproxy->options & PR_O_TRANSP)
6253 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006254
Willy Tarreau1620ec32011-08-06 17:05:02 +02006255 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6256 if (curproxy->options & PR_O_DISABLE404) {
6257 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6258 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6259 err_code |= ERR_WARN;
6260 curproxy->options &= ~PR_O_DISABLE404;
6261 }
6262 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6263 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6264 "send-state", proxy_type_str(curproxy), curproxy->id);
6265 err_code |= ERR_WARN;
6266 curproxy->options &= ~PR_O2_CHK_SNDST;
6267 }
Willy Tarreauef781042010-01-27 11:53:01 +01006268 }
6269
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006270 /* if a default backend was specified, let's find it */
6271 if (curproxy->defbe.name) {
6272 struct proxy *target;
6273
Alex Williams96532db2009-11-01 21:27:13 -05006274 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006275 if (!target) {
6276 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6277 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006278 cfgerr++;
6279 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006280 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6281 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006282 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006283 } else {
6284 free(curproxy->defbe.name);
6285 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006286
6287 /* Emit a warning if this proxy also has some servers */
6288 if (curproxy->srv) {
6289 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6290 curproxy->id);
6291 err_code |= ERR_WARN;
6292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
6294 }
6295
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006296 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006297 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6298 /* map jump target for ACT_SETBE in req_rep chain */
6299 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006300 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006301 struct proxy *target;
6302
Willy Tarreaua496b602006-12-17 23:15:24 +01006303 if (exp->action != ACT_SETBE)
6304 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006305
Alex Williams96532db2009-11-01 21:27:13 -05006306 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006307 if (!target) {
6308 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6309 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006310 cfgerr++;
6311 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006312 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6313 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006314 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006315 } else {
6316 free((void *)exp->replace);
6317 exp->replace = (const char *)target;
6318 }
6319 }
6320 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006321
6322 /* find the target proxy for 'use_backend' rules */
6323 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006324 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006325 struct logformat_node *node;
6326 char *pxname;
6327
6328 /* Try to parse the string as a log format expression. If the result
6329 * of the parsing is only one entry containing a simple string, then
6330 * it's a standard string corresponding to a static rule, thus the
6331 * parsing is cancelled and be.name is restored to be resolved.
6332 */
6333 pxname = rule->be.name;
6334 LIST_INIT(&rule->be.expr);
6335 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6336 curproxy->conf.args.file, curproxy->conf.args.line);
6337 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6338
6339 if (!LIST_ISEMPTY(&rule->be.expr)) {
6340 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6341 rule->dynamic = 1;
6342 free(pxname);
6343 continue;
6344 }
6345 /* simple string: free the expression and fall back to static rule */
6346 free(node->arg);
6347 free(node);
6348 }
6349
6350 rule->dynamic = 0;
6351 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006352
Alex Williams96532db2009-11-01 21:27:13 -05006353 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006354
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006355 if (!target) {
6356 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6357 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006358 cfgerr++;
6359 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006360 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6361 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006362 cfgerr++;
6363 } else {
6364 free((void *)rule->be.name);
6365 rule->be.backend = target;
6366 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006367 }
6368
Willy Tarreau5436afc2014-09-16 12:17:36 +02006369 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006370 list_for_each_entry(srule, &curproxy->server_rules, list) {
6371 struct server *target = findserver(curproxy, srule->srv.name);
6372
6373 if (!target) {
6374 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6375 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6376 cfgerr++;
6377 continue;
6378 }
6379 free((void *)srule->srv.name);
6380 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006381 }
6382
Emeric Brunb982a3d2010-01-04 15:45:53 +01006383 /* find the target table for 'stick' rules */
6384 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6385 struct proxy *target;
6386
Emeric Brun1d33b292010-01-04 15:47:17 +01006387 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6388 if (mrule->flags & STK_IS_STORE)
6389 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6390
Emeric Brunb982a3d2010-01-04 15:45:53 +01006391 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006392 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006393 else
6394 target = curproxy;
6395
6396 if (!target) {
6397 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6398 curproxy->id, mrule->table.name);
6399 cfgerr++;
6400 }
6401 else if (target->table.size == 0) {
6402 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6403 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6404 cfgerr++;
6405 }
Willy Tarreau12785782012-04-27 21:37:17 +02006406 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6407 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006408 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6409 cfgerr++;
6410 }
6411 else {
6412 free((void *)mrule->table.name);
6413 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006414 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006415 }
6416 }
6417
6418 /* find the target table for 'store response' rules */
6419 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6420 struct proxy *target;
6421
Emeric Brun1d33b292010-01-04 15:47:17 +01006422 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6423
Emeric Brunb982a3d2010-01-04 15:45:53 +01006424 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006425 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006426 else
6427 target = curproxy;
6428
6429 if (!target) {
6430 Alert("Proxy '%s': unable to find store table '%s'.\n",
6431 curproxy->id, mrule->table.name);
6432 cfgerr++;
6433 }
6434 else if (target->table.size == 0) {
6435 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6436 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6437 cfgerr++;
6438 }
Willy Tarreau12785782012-04-27 21:37:17 +02006439 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6440 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006441 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6442 cfgerr++;
6443 }
6444 else {
6445 free((void *)mrule->table.name);
6446 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006447 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006448 }
6449 }
6450
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006451 /* find the target table for 'tcp-request' layer 4 rules */
6452 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6453 struct proxy *target;
6454
Willy Tarreaub4c84932013-07-23 19:15:30 +02006455 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006456 continue;
6457
6458 if (trule->act_prm.trk_ctr.table.n)
6459 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6460 else
6461 target = curproxy;
6462
6463 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006464 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6465 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006466 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006467 cfgerr++;
6468 }
6469 else if (target->table.size == 0) {
6470 Alert("Proxy '%s': table '%s' used but not configured.\n",
6471 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6472 cfgerr++;
6473 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006474 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6475 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6476 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 +01006477 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006478 cfgerr++;
6479 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006480 else {
6481 free(trule->act_prm.trk_ctr.table.n);
6482 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006483 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006484 * to pass a list of counters to track and allocate them right here using
6485 * stktable_alloc_data_type().
6486 */
6487 }
6488 }
6489
Willy Tarreaud1f96522010-08-03 19:34:32 +02006490 /* find the target table for 'tcp-request' layer 6 rules */
6491 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6492 struct proxy *target;
6493
Willy Tarreaub4c84932013-07-23 19:15:30 +02006494 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006495 continue;
6496
6497 if (trule->act_prm.trk_ctr.table.n)
6498 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6499 else
6500 target = curproxy;
6501
6502 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006503 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6504 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006505 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006506 cfgerr++;
6507 }
6508 else if (target->table.size == 0) {
6509 Alert("Proxy '%s': table '%s' used but not configured.\n",
6510 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6511 cfgerr++;
6512 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006513 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6514 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6515 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 +01006516 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006517 cfgerr++;
6518 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006519 else {
6520 free(trule->act_prm.trk_ctr.table.n);
6521 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006522 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006523 * to pass a list of counters to track and allocate them right here using
6524 * stktable_alloc_data_type().
6525 */
6526 }
6527 }
6528
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006529 /* move any "block" rules at the beginning of the http-request rules */
6530 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6531 /* insert block_rules into http_req_rules at the beginning */
6532 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6533 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6534 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6535 curproxy->http_req_rules.n = curproxy->block_rules.n;
6536 LIST_INIT(&curproxy->block_rules);
6537 }
6538
Emeric Brun32da3c42010-09-23 18:39:19 +02006539 if (curproxy->table.peers.name) {
6540 struct peers *curpeers = peers;
6541
6542 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6543 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6544 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006545 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006546 break;
6547 }
6548 }
6549
6550 if (!curpeers) {
6551 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6552 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006553 free((void *)curproxy->table.peers.name);
6554 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006555 cfgerr++;
6556 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006557 else if (curpeers->state == PR_STSTOPPED) {
6558 /* silently disable this peers section */
6559 curproxy->table.peers.p = NULL;
6560 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006561 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006562 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6563 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006564 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006565 cfgerr++;
6566 }
6567 }
6568
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006569 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006570 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006571 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6572 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6573 "proxy", curproxy->id);
6574 cfgerr++;
6575 goto out_uri_auth_compat;
6576 }
6577
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006578 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006579 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006580 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006581 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006582
Willy Tarreau95fa4692010-02-01 13:05:50 +01006583 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6584 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006585
6586 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006587 uri_auth_compat_req[i++] = "realm";
6588 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6589 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006590
Willy Tarreau95fa4692010-02-01 13:05:50 +01006591 uri_auth_compat_req[i++] = "unless";
6592 uri_auth_compat_req[i++] = "{";
6593 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6594 uri_auth_compat_req[i++] = "}";
6595 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006596
Willy Tarreauff011f22011-01-06 17:51:27 +01006597 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6598 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006599 cfgerr++;
6600 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006601 }
6602
Willy Tarreauff011f22011-01-06 17:51:27 +01006603 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006604
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006605 if (curproxy->uri_auth->auth_realm) {
6606 free(curproxy->uri_auth->auth_realm);
6607 curproxy->uri_auth->auth_realm = NULL;
6608 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006609
6610 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006611 }
6612out_uri_auth_compat:
6613
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006614 /* compile the log format */
6615 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006616 if (curproxy->conf.logformat_string != default_http_log_format &&
6617 curproxy->conf.logformat_string != default_tcp_log_format &&
6618 curproxy->conf.logformat_string != clf_http_log_format)
6619 free(curproxy->conf.logformat_string);
6620 curproxy->conf.logformat_string = NULL;
6621 free(curproxy->conf.lfs_file);
6622 curproxy->conf.lfs_file = NULL;
6623 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006624 }
6625
Willy Tarreau62a61232013-04-12 18:13:46 +02006626 if (curproxy->conf.logformat_string) {
6627 curproxy->conf.args.ctx = ARGC_LOG;
6628 curproxy->conf.args.file = curproxy->conf.lfs_file;
6629 curproxy->conf.args.line = curproxy->conf.lfs_line;
6630 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006631 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006632 curproxy->conf.args.file = NULL;
6633 curproxy->conf.args.line = 0;
6634 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006635
Willy Tarreau62a61232013-04-12 18:13:46 +02006636 if (curproxy->conf.uniqueid_format_string) {
6637 curproxy->conf.args.ctx = ARGC_UIF;
6638 curproxy->conf.args.file = curproxy->conf.uif_file;
6639 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006640 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006641 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006642 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006643 curproxy->conf.args.file = NULL;
6644 curproxy->conf.args.line = 0;
6645 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006646
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006647 /* only now we can check if some args remain unresolved.
6648 * This must be done after the users and groups resolution.
6649 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006650 cfgerr += smp_resolve_args(curproxy);
6651 if (!cfgerr)
6652 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006653
Willy Tarreau2738a142006-07-08 17:28:09 +02006654 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006655 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006656 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006657 (!curproxy->timeout.connect ||
6658 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006659 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006660 " | While not properly invalid, you will certainly encounter various problems\n"
6661 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006662 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006663 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006664 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006665 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006666
Willy Tarreau1fa31262007-12-03 00:36:16 +01006667 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6668 * We must still support older configurations, so let's find out whether those
6669 * parameters have been set or must be copied from contimeouts.
6670 */
6671 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006672 if (!curproxy->timeout.tarpit ||
6673 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006674 /* tarpit timeout not set. We search in the following order:
6675 * default.tarpit, curr.connect, default.connect.
6676 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006677 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006678 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006679 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006680 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006681 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006682 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006683 }
6684 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006685 (!curproxy->timeout.queue ||
6686 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006687 /* queue timeout not set. We search in the following order:
6688 * default.queue, curr.connect, default.connect.
6689 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006690 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006691 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006692 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006693 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006694 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006695 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006696 }
6697 }
6698
Willy Tarreau1620ec32011-08-06 17:05:02 +02006699 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006700 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6701 curproxy->check_req = (char *)malloc(curproxy->check_len);
6702 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006703 }
6704
Willy Tarreau215663d2014-06-13 18:30:23 +02006705 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6706 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6707 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6708 proxy_type_str(curproxy), curproxy->id);
6709 err_code |= ERR_WARN;
6710 }
6711
Willy Tarreau193b8c62012-11-22 00:17:38 +01006712 /* ensure that cookie capture length is not too large */
6713 if (curproxy->capture_len >= global.tune.cookie_len) {
6714 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6715 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6716 err_code |= ERR_WARN;
6717 curproxy->capture_len = global.tune.cookie_len - 1;
6718 }
6719
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006720 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006721 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006722 curproxy->req_cap_pool = create_pool("ptrcap",
6723 curproxy->nb_req_cap * sizeof(char *),
6724 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006725 }
6726
6727 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006728 curproxy->rsp_cap_pool = create_pool("ptrcap",
6729 curproxy->nb_rsp_cap * sizeof(char *),
6730 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006731 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006732
Willy Tarreaubaaee002006-06-26 02:48:02 +02006733 /* first, we will invert the servers list order */
6734 newsrv = NULL;
6735 while (curproxy->srv) {
6736 struct server *next;
6737
6738 next = curproxy->srv->next;
6739 curproxy->srv->next = newsrv;
6740 newsrv = curproxy->srv;
6741 if (!next)
6742 break;
6743 curproxy->srv = next;
6744 }
6745
Willy Tarreau17edc812014-01-03 12:14:34 +01006746 /* Check that no server name conflicts. This causes trouble in the stats.
6747 * We only emit a warning for the first conflict affecting each server,
6748 * in order to avoid combinatory explosion if all servers have the same
6749 * name. We do that only for servers which do not have an explicit ID,
6750 * because these IDs were made also for distinguishing them and we don't
6751 * want to annoy people who correctly manage them.
6752 */
6753 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6754 struct server *other_srv;
6755
6756 if (newsrv->puid)
6757 continue;
6758
6759 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6760 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6761 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6762 newsrv->conf.file, newsrv->conf.line,
6763 proxy_type_str(curproxy), curproxy->id,
6764 newsrv->id, other_srv->conf.line);
6765 break;
6766 }
6767 }
6768 }
6769
Willy Tarreaudd701652010-05-25 23:03:02 +02006770 /* assign automatic UIDs to servers which don't have one yet */
6771 next_id = 1;
6772 newsrv = curproxy->srv;
6773 while (newsrv != NULL) {
6774 if (!newsrv->puid) {
6775 /* server ID not set, use automatic numbering with first
6776 * spare entry starting with next_svid.
6777 */
6778 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6779 newsrv->conf.id.key = newsrv->puid = next_id;
6780 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6781 }
6782 next_id++;
6783 newsrv = newsrv->next;
6784 }
6785
Willy Tarreau20697042007-11-15 23:26:18 +01006786 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006787 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006788
Willy Tarreau62c3be22012-01-20 13:12:32 +01006789 /*
6790 * If this server supports a maxconn parameter, it needs a dedicated
6791 * tasks to fill the emptied slots when a connection leaves.
6792 * Also, resolve deferred tracking dependency if needed.
6793 */
6794 newsrv = curproxy->srv;
6795 while (newsrv != NULL) {
6796 if (newsrv->minconn > newsrv->maxconn) {
6797 /* Only 'minconn' was specified, or it was higher than or equal
6798 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6799 * this will avoid further useless expensive computations.
6800 */
6801 newsrv->maxconn = newsrv->minconn;
6802 } else if (newsrv->maxconn && !newsrv->minconn) {
6803 /* minconn was not specified, so we set it to maxconn */
6804 newsrv->minconn = newsrv->maxconn;
6805 }
6806
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006807#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006808 if (newsrv->use_ssl || newsrv->check.use_ssl)
6809 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006810#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006811
Willy Tarreau2f075e92013-12-03 11:11:34 +01006812 /* set the check type on the server */
6813 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6814
Willy Tarreau62c3be22012-01-20 13:12:32 +01006815 if (newsrv->trackit) {
6816 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006817 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006818 char *pname, *sname;
6819
6820 pname = newsrv->trackit;
6821 sname = strrchr(pname, '/');
6822
6823 if (sname)
6824 *sname++ = '\0';
6825 else {
6826 sname = pname;
6827 pname = NULL;
6828 }
6829
6830 if (pname) {
6831 px = findproxy(pname, PR_CAP_BE);
6832 if (!px) {
6833 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6834 proxy_type_str(curproxy), curproxy->id,
6835 newsrv->id, pname);
6836 cfgerr++;
6837 goto next_srv;
6838 }
6839 } else
6840 px = curproxy;
6841
6842 srv = findserver(px, sname);
6843 if (!srv) {
6844 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6845 proxy_type_str(curproxy), curproxy->id,
6846 newsrv->id, sname);
6847 cfgerr++;
6848 goto next_srv;
6849 }
6850
Willy Tarreau32091232014-05-16 13:52:00 +02006851 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6852 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6853 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006854 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006855 "tracking as it does not have any check nor agent enabled.\n",
6856 proxy_type_str(curproxy), curproxy->id,
6857 newsrv->id, px->id, srv->id);
6858 cfgerr++;
6859 goto next_srv;
6860 }
6861
6862 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6863
6864 if (loop) {
6865 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6866 "belongs to a tracking chain looping back to %s/%s.\n",
6867 proxy_type_str(curproxy), curproxy->id,
6868 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006869 cfgerr++;
6870 goto next_srv;
6871 }
6872
6873 if (curproxy != px &&
6874 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6875 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6876 "tracking: disable-on-404 option inconsistency.\n",
6877 proxy_type_str(curproxy), curproxy->id,
6878 newsrv->id, px->id, srv->id);
6879 cfgerr++;
6880 goto next_srv;
6881 }
6882
6883 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006884 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006885 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006886 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006887 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006888 }
6889
6890 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006891 newsrv->tracknext = srv->trackers;
6892 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006893
6894 free(newsrv->trackit);
6895 newsrv->trackit = NULL;
6896 }
6897 next_srv:
6898 newsrv = newsrv->next;
6899 }
6900
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006901 /* We have to initialize the server lookup mechanism depending
6902 * on what LB algorithm was choosen.
6903 */
6904
6905 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6906 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6907 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006908 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6909 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6910 init_server_map(curproxy);
6911 } else {
6912 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6913 fwrr_init_server_groups(curproxy);
6914 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006915 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006916
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006917 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006918 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6919 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6920 fwlc_init_server_tree(curproxy);
6921 } else {
6922 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6923 fas_init_server_tree(curproxy);
6924 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006925 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006926
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006927 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006928 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6929 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6930 chash_init_server_tree(curproxy);
6931 } else {
6932 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6933 init_server_map(curproxy);
6934 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006935 break;
6936 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006937
6938 if (curproxy->options & PR_O_LOGASAP)
6939 curproxy->to_log &= ~LW_BYTES;
6940
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006941 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006942 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006943 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6944 proxy_type_str(curproxy), curproxy->id);
6945 err_code |= ERR_WARN;
6946 }
6947
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006948 if (curproxy->mode != PR_MODE_HTTP) {
6949 int optnum;
6950
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006951 if (curproxy->uri_auth) {
6952 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6953 proxy_type_str(curproxy), curproxy->id);
6954 err_code |= ERR_WARN;
6955 curproxy->uri_auth = NULL;
6956 }
6957
Willy Tarreau87cf5142011-08-19 22:57:24 +02006958 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006959 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6960 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6961 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006962 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006963 }
6964
6965 if (curproxy->options & PR_O_ORGTO) {
6966 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6967 "originalto", proxy_type_str(curproxy), curproxy->id);
6968 err_code |= ERR_WARN;
6969 curproxy->options &= ~PR_O_ORGTO;
6970 }
6971
6972 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6973 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6974 (curproxy->cap & cfg_opts[optnum].cap) &&
6975 (curproxy->options & cfg_opts[optnum].val)) {
6976 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6977 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6978 err_code |= ERR_WARN;
6979 curproxy->options &= ~cfg_opts[optnum].val;
6980 }
6981 }
6982
6983 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6984 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6985 (curproxy->cap & cfg_opts2[optnum].cap) &&
6986 (curproxy->options2 & cfg_opts2[optnum].val)) {
6987 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6988 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6989 err_code |= ERR_WARN;
6990 curproxy->options2 &= ~cfg_opts2[optnum].val;
6991 }
6992 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006993
Pieter Baauwd551fb52013-05-08 22:49:23 +02006994#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006995 if (curproxy->conn_src.bind_hdr_occ) {
6996 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006997 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006998 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006999 err_code |= ERR_WARN;
7000 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007001#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007002 }
7003
Willy Tarreaubaaee002006-06-26 02:48:02 +02007004 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007005 * ensure that we're not cross-dressing a TCP server into HTTP.
7006 */
7007 newsrv = curproxy->srv;
7008 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007009 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007010 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7011 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007012 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007013 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007014
Willy Tarreau0cec3312011-10-31 13:49:26 +01007015 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7016 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7017 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7018 err_code |= ERR_WARN;
7019 }
7020
Willy Tarreauc93cd162014-05-13 15:54:22 +02007021 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007022 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7023 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7024 err_code |= ERR_WARN;
7025 }
7026
Pieter Baauwd551fb52013-05-08 22:49:23 +02007027#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007028 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7029 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007030 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 +01007031 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007032 err_code |= ERR_WARN;
7033 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007034#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007035 newsrv = newsrv->next;
7036 }
7037
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007038 /* check if we have a frontend with "tcp-request content" looking at L7
7039 * with no inspect-delay
7040 */
7041 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7042 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7043 if (trule->action == TCP_ACT_CAPTURE &&
7044 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7045 break;
7046 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7047 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7048 break;
7049 }
7050
7051 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7052 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7053 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7054 " This means that these rules will randomly find their contents. This can be fixed by"
7055 " setting the tcp-request inspect-delay.\n",
7056 proxy_type_str(curproxy), curproxy->id);
7057 err_code |= ERR_WARN;
7058 }
7059 }
7060
Willy Tarreauc1a21672009-08-16 22:37:44 +02007061 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007062 if (!curproxy->accept)
7063 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007064
Willy Tarreauc1a21672009-08-16 22:37:44 +02007065 if (curproxy->tcp_req.inspect_delay ||
7066 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007067 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007068
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007069 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007070 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007071 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007072 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007073
7074 /* both TCP and HTTP must check switching rules */
7075 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7076 }
7077
7078 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007079 if (curproxy->tcp_req.inspect_delay ||
7080 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7081 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7082
Emeric Brun97679e72010-09-23 17:56:44 +02007083 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7084 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7085
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007086 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007087 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007088 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007089 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007090
7091 /* If the backend does requires RDP cookie persistence, we have to
7092 * enable the corresponding analyser.
7093 */
7094 if (curproxy->options2 & PR_O2_RDPC_PRST)
7095 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7096 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007097 }
7098
7099 /***********************************************************/
7100 /* At this point, target names have already been resolved. */
7101 /***********************************************************/
7102
7103 /* Check multi-process mode compatibility */
7104
7105 if (global.nbproc > 1 && global.stats_fe) {
7106 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7107 unsigned long mask;
7108
7109 mask = nbits(global.nbproc);
7110 if (global.stats_fe->bind_proc)
7111 mask &= global.stats_fe->bind_proc;
7112
7113 if (bind_conf->bind_proc)
7114 mask &= bind_conf->bind_proc;
7115
7116 /* stop here if more than one process is used */
David Carlier6de4c2f2015-07-02 07:00:17 +00007117 if (my_popcountl(mask) > 1)
Willy Tarreau91b00c22014-09-16 13:41:21 +02007118 break;
7119 }
7120 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7121 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");
7122 }
7123 }
7124
7125 /* Make each frontend inherit bind-process from its listeners when not specified. */
7126 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7127 if (curproxy->bind_proc)
7128 continue;
7129
7130 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7131 unsigned long mask;
7132
Willy Tarreau01760ad2015-05-04 21:57:58 +02007133 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007134 curproxy->bind_proc |= mask;
7135 }
7136
7137 if (!curproxy->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007138 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007139 }
7140
7141 if (global.stats_fe) {
7142 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7143 unsigned long mask;
7144
Cyril Bonté32e4f252016-02-24 00:14:54 +01007145 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau91b00c22014-09-16 13:41:21 +02007146 global.stats_fe->bind_proc |= mask;
7147 }
7148 if (!global.stats_fe->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007149 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007150 }
7151
Willy Tarreaub3228c82014-10-01 20:50:17 +02007152 /* propagate bindings from frontends to backends. Don't do it if there
7153 * are any fatal errors as we must not call it with unresolved proxies.
7154 */
7155 if (!cfgerr) {
7156 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7157 if (curproxy->cap & PR_CAP_FE)
7158 propagate_processes(curproxy, NULL);
7159 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007160 }
7161
7162 /* Bind each unbound backend to all processes when not specified. */
7163 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7164 if (curproxy->bind_proc)
7165 continue;
Willy Tarreau01760ad2015-05-04 21:57:58 +02007166 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007167 }
7168
7169 /*******************************************************/
7170 /* At this step, all proxies have a non-null bind_proc */
7171 /*******************************************************/
7172
7173 /* perform the final checks before creating tasks */
7174
7175 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7176 struct listener *listener;
7177 unsigned int next_id;
7178 int nbproc;
7179
David Carlier6de4c2f2015-07-02 07:00:17 +00007180 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007181
Emeric Brunc52962f2012-11-15 18:28:02 +01007182#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007183 /* Configure SSL for each bind line.
7184 * Note: if configuration fails at some point, the ->ctx member
7185 * remains NULL so that listeners can later detach.
7186 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007187 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007188 int alloc_ctx;
7189
Emeric Brunc52962f2012-11-15 18:28:02 +01007190 if (!bind_conf->is_ssl) {
7191 if (bind_conf->default_ctx) {
7192 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7193 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7194 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007195 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007196 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007197 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007198 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007199 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007200 cfgerr++;
7201 continue;
7202 }
7203
Emeric Brun8dc60392014-05-09 13:52:00 +02007204 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007205 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007206 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7207 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");
7208 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007209 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007210 cfgerr++;
7211 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007212 }
7213
Emeric Brunfc0421f2012-09-07 17:30:07 +02007214 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007215 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007216 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007217#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007218
Willy Tarreaue6b98942007-10-29 01:09:36 +01007219 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007220 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007221 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007222 if (!listener->luid) {
7223 /* listener ID not set, use automatic numbering with first
7224 * spare entry starting with next_luid.
7225 */
7226 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7227 listener->conf.id.key = listener->luid = next_id;
7228 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007229 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007230 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007231
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007232 /* enable separate counters */
7233 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7234 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007235 if (!listener->name)
7236 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007237 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007238
Willy Tarreaue6b98942007-10-29 01:09:36 +01007239 if (curproxy->options & PR_O_TCP_NOLING)
7240 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007241 if (!listener->maxconn)
7242 listener->maxconn = curproxy->maxconn;
7243 if (!listener->backlog)
7244 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007245 if (!listener->maxaccept)
7246 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7247
7248 /* we want to have an optimal behaviour on single process mode to
7249 * maximize the work at once, but in multi-process we want to keep
7250 * some fairness between processes, so we target half of the max
7251 * number of events to be balanced over all the processes the proxy
7252 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7253 * used to disable the limit.
7254 */
7255 if (listener->maxaccept > 0) {
7256 if (nbproc > 1)
7257 listener->maxaccept = (listener->maxaccept + 1) / 2;
7258 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7259 }
7260
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007261 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007262 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007263 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007264 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007265
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007266 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7267 listener->options |= LI_O_TCP_RULES;
7268
Willy Tarreaude3041d2010-05-31 10:56:17 +02007269 if (curproxy->mon_mask.s_addr)
7270 listener->options |= LI_O_CHK_MONNET;
7271
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007272 /* smart accept mode is automatic in HTTP mode */
7273 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007274 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007275 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7276 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007277 }
7278
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007279 /* Release unused SSL configs */
7280 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7281 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007282 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007283#ifdef USE_OPENSSL
7284 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007285 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007286 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007287 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007288 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007289#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007290 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007291
Willy Tarreau102df612014-05-07 23:56:38 +02007292 if (nbproc > 1) {
7293 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007294 int count, maxproc = 0;
7295
7296 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carlier6de4c2f2015-07-02 07:00:17 +00007297 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreau036a83e2014-09-16 15:11:04 +02007298 if (count > maxproc)
7299 maxproc = count;
7300 }
7301 /* backends have 0, frontends have 1 or more */
7302 if (maxproc != 1)
7303 Warning("Proxy '%s': in multi-process mode, stats will be"
7304 " limited to process assigned to the current request.\n",
7305 curproxy->id);
7306
Willy Tarreau102df612014-05-07 23:56:38 +02007307 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7308 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7309 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007310 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007311 }
Willy Tarreau102df612014-05-07 23:56:38 +02007312 if (curproxy->appsession_name) {
7313 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7314 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007315 }
Willy Tarreau102df612014-05-07 23:56:38 +02007316 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7317 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7318 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007319 }
7320 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007321
7322 /* create the task associated with the proxy */
7323 curproxy->task = task_new();
7324 if (curproxy->task) {
7325 curproxy->task->context = curproxy;
7326 curproxy->task->process = manage_proxy;
7327 /* no need to queue, it will be done automatically if some
7328 * listener gets limited.
7329 */
7330 curproxy->task->expire = TICK_ETERNITY;
7331 } else {
7332 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7333 curproxy->id);
7334 cfgerr++;
7335 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007336 }
7337
Willy Tarreaufbb78422011-06-05 15:38:35 +02007338 /* automatically compute fullconn if not set. We must not do it in the
7339 * loop above because cross-references are not yet fully resolved.
7340 */
7341 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7342 /* If <fullconn> is not set, let's set it to 10% of the sum of
7343 * the possible incoming frontend's maxconns.
7344 */
7345 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7346 struct proxy *fe;
7347 int total = 0;
7348
7349 /* sum up the number of maxconns of frontends which
7350 * reference this backend at least once or which are
7351 * the same one ('listen').
7352 */
7353 for (fe = proxy; fe; fe = fe->next) {
7354 struct switching_rule *rule;
7355 struct hdr_exp *exp;
7356 int found = 0;
7357
7358 if (!(fe->cap & PR_CAP_FE))
7359 continue;
7360
7361 if (fe == curproxy) /* we're on a "listen" instance */
7362 found = 1;
7363
7364 if (fe->defbe.be == curproxy) /* "default_backend" */
7365 found = 1;
7366
7367 /* check if a "use_backend" rule matches */
7368 if (!found) {
7369 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007370 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007371 found = 1;
7372 break;
7373 }
7374 }
7375 }
7376
7377 /* check if a "reqsetbe" rule matches */
7378 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7379 if (exp->action == ACT_SETBE &&
7380 (struct proxy *)exp->replace == curproxy) {
7381 found = 1;
7382 break;
7383 }
7384 }
7385
7386 /* now we've checked all possible ways to reference a backend
7387 * from a frontend.
7388 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007389 if (!found)
7390 continue;
7391 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007392 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007393 /* we have the sum of the maxconns in <total>. We only
7394 * keep 10% of that sum to set the default fullconn, with
7395 * a hard minimum of 1 (to avoid a divide by zero).
7396 */
7397 curproxy->fullconn = (total + 9) / 10;
7398 if (!curproxy->fullconn)
7399 curproxy->fullconn = 1;
7400 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007401 }
7402
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007403 /*
7404 * Recount currently required checks.
7405 */
7406
7407 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7408 int optnum;
7409
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007410 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7411 if (curproxy->options & cfg_opts[optnum].val)
7412 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007413
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007414 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7415 if (curproxy->options2 & cfg_opts2[optnum].val)
7416 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007417 }
7418
Willy Tarreaucdb5e922015-05-01 19:12:05 +02007419 /* compute the required process bindings for the peers */
7420 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7421 if (curproxy->table.peers.p)
7422 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7423
Willy Tarreau122541c2011-09-07 21:24:49 +02007424 if (peers) {
7425 struct peers *curpeers = peers, **last;
7426 struct peer *p, *pb;
7427
Willy Tarreauab0419d2015-05-01 19:15:17 +02007428 /* Remove all peers sections which don't have a valid listener,
7429 * which are not used by any table, or which are bound to more
7430 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02007431 */
7432 last = &peers;
7433 while (*last) {
7434 curpeers = *last;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007435
7436 if (curpeers->state == PR_STSTOPPED) {
7437 /* the "disabled" keyword was present */
7438 if (curpeers->peers_fe)
7439 stop_proxy(curpeers->peers_fe);
7440 curpeers->peers_fe = NULL;
7441 }
7442 else if (!curpeers->peers_fe) {
7443 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7444 curpeers->id, localpeer);
7445 }
David Carlier6de4c2f2015-07-02 07:00:17 +00007446 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreauab0419d2015-05-01 19:15:17 +02007447 /* either it's totally stopped or too much used */
7448 if (curpeers->peers_fe->bind_proc) {
7449 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreaua5d7d072015-05-04 21:48:51 +02007450 "running in different processes (%d different ones). "
7451 "Check global.nbproc and all tables' bind-process "
David Carlier6de4c2f2015-07-02 07:00:17 +00007452 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreauab0419d2015-05-01 19:15:17 +02007453 cfgerr++;
7454 }
7455 stop_proxy(curpeers->peers_fe);
7456 curpeers->peers_fe = NULL;
7457 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02007458 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007459 last = &curpeers->next;
7460 continue;
7461 }
7462
Willy Tarreau34d05b02015-05-01 20:02:17 +02007463 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007464 p = curpeers->remote;
7465 while (p) {
7466 pb = p->next;
7467 free(p->id);
7468 free(p);
7469 p = pb;
7470 }
7471
7472 /* Destroy and unlink this curpeers section.
7473 * Note: curpeers is backed up into *last.
7474 */
7475 free(curpeers->id);
7476 curpeers = curpeers->next;
7477 free(*last);
7478 *last = curpeers;
7479 }
7480 }
7481
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007482 /* initialize stick-tables on backend capable proxies. This must not
7483 * be done earlier because the data size may be discovered while parsing
7484 * other proxies.
7485 */
7486 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7487 if (curproxy->state == PR_STSTOPPED)
7488 continue;
7489
7490 if (!stktable_init(&curproxy->table)) {
7491 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7492 cfgerr++;
7493 }
7494 }
7495
Willy Tarreau34eb6712011-10-24 18:15:04 +02007496 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007497 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007498 MEM_F_SHARED);
7499
Willy Tarreaubb925012009-07-23 13:36:36 +02007500 if (cfgerr > 0)
7501 err_code |= ERR_ALERT | ERR_FATAL;
7502 out:
7503 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007504}
7505
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007506/*
7507 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7508 * parsing sessions.
7509 */
7510void cfg_register_keywords(struct cfg_kw_list *kwl)
7511{
7512 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7513}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007514
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007515/*
7516 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7517 */
7518void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7519{
7520 LIST_DEL(&kwl->list);
7521 LIST_INIT(&kwl->list);
7522}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007523
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007524/* this function register new section in the haproxy configuration file.
7525 * <section_name> is the name of this new section and <section_parser>
7526 * is the called parser. If two section declaration have the same name,
7527 * only the first declared is used.
7528 */
7529int cfg_register_section(char *section_name,
7530 int (*section_parser)(const char *, int, char **, int))
7531{
7532 struct cfg_section *cs;
7533
7534 cs = calloc(1, sizeof(*cs));
7535 if (!cs) {
7536 Alert("register section '%s': out of memory.\n", section_name);
7537 return 0;
7538 }
7539
7540 cs->section_name = section_name;
7541 cs->section_parser = section_parser;
7542
7543 LIST_ADDQ(&sections, &cs->list);
7544
7545 return 1;
7546}
7547
Willy Tarreaubaaee002006-06-26 02:48:02 +02007548/*
7549 * Local variables:
7550 * c-indent-level: 8
7551 * c-basic-offset: 8
7552 * End:
7553 */