blob: c79ddc234c30f24e3f04940a00977d8615d884d1 [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 }
Baptiste Assmannd5760be2016-03-11 17:21:15 +0100916 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
917 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
918 err_code |= ERR_WARN;
919 goto out;
920 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200921 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200922 /* user/group name handling */
923 else if (!strcmp(args[0], "user")) {
924 struct passwd *ha_user;
925 if (global.uid != 0) {
926 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200927 err_code |= ERR_ALERT;
928 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200929 }
930 errno = 0;
931 ha_user = getpwnam(args[1]);
932 if (ha_user != NULL) {
933 global.uid = (int)ha_user->pw_uid;
934 }
935 else {
936 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 +0200937 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200938 }
939 }
940 else if (!strcmp(args[0], "group")) {
941 struct group *ha_group;
942 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200943 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200944 err_code |= ERR_ALERT;
945 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200946 }
947 errno = 0;
948 ha_group = getgrnam(args[1]);
949 if (ha_group != NULL) {
950 global.gid = (int)ha_group->gr_gid;
951 }
952 else {
953 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 +0200954 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200955 }
956 }
957 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200958 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200959 if (*(args[1]) == 0) {
960 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT | ERR_FATAL;
962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100965 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
966 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
967 file, linenum, args[0], LONGBITS, global.nbproc);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200971 }
972 else if (!strcmp(args[0], "maxconn")) {
973 if (global.maxconn != 0) {
974 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200975 err_code |= ERR_ALERT;
976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200977 }
978 if (*(args[1]) == 0) {
979 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200980 err_code |= ERR_ALERT | ERR_FATAL;
981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200982 }
983 global.maxconn = atol(args[1]);
984#ifdef SYSTEM_MAXCONN
985 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
986 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);
987 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200988 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200989 }
990#endif /* SYSTEM_MAXCONN */
991 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200992 else if (!strcmp(args[0], "maxsslconn")) {
993#ifdef USE_OPENSSL
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999 global.maxsslconn = atol(args[1]);
1000#else
Emeric Brun0914df82012-10-02 18:45:42 +02001001 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001004#endif
1005 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001006 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1007#ifdef USE_OPENSSL
1008 if (*(args[1]) == 0) {
1009 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1010 err_code |= ERR_ALERT | ERR_FATAL;
1011 goto out;
1012 }
1013 free(global.listen_default_ciphers);
1014 global.listen_default_ciphers = strdup(args[1]);
1015#else
1016 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1017 err_code |= ERR_ALERT | ERR_FATAL;
1018 goto out;
1019#endif
1020 }
1021 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1022#ifdef USE_OPENSSL
1023 if (*(args[1]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 free(global.connect_default_ciphers);
1029 global.connect_default_ciphers = strdup(args[1]);
1030#else
1031 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1032 err_code |= ERR_ALERT | ERR_FATAL;
1033 goto out;
1034#endif
1035 }
Emeric Brun850efd52014-01-29 12:24:34 +01001036 else if (!strcmp(args[0], "ssl-server-verify")) {
1037 if (*(args[1]) == 0) {
1038 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 if (strcmp(args[1],"none") == 0)
1043 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1044 else if (strcmp(args[1],"required") == 0)
1045 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1046 else {
1047 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050 }
1051 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001052 else if (!strcmp(args[0], "maxconnrate")) {
1053 if (global.cps_lim != 0) {
1054 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1055 err_code |= ERR_ALERT;
1056 goto out;
1057 }
1058 if (*(args[1]) == 0) {
1059 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1060 err_code |= ERR_ALERT | ERR_FATAL;
1061 goto out;
1062 }
1063 global.cps_lim = atol(args[1]);
1064 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001065 else if (!strcmp(args[0], "maxsessrate")) {
1066 if (global.sps_lim != 0) {
1067 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1068 err_code |= ERR_ALERT;
1069 goto out;
1070 }
1071 if (*(args[1]) == 0) {
1072 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1073 err_code |= ERR_ALERT | ERR_FATAL;
1074 goto out;
1075 }
1076 global.sps_lim = atol(args[1]);
1077 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001078 else if (!strcmp(args[0], "maxsslrate")) {
1079 if (global.ssl_lim != 0) {
1080 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1081 err_code |= ERR_ALERT;
1082 goto out;
1083 }
1084 if (*(args[1]) == 0) {
1085 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089 global.ssl_lim = atol(args[1]);
1090 }
William Lallemandd85f9172012-11-09 17:05:39 +01001091 else if (!strcmp(args[0], "maxcomprate")) {
1092 if (*(args[1]) == 0) {
1093 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1094 err_code |= ERR_ALERT | ERR_FATAL;
1095 goto out;
1096 }
1097 global.comp_rate_lim = atoi(args[1]) * 1024;
1098 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001099 else if (!strcmp(args[0], "maxpipes")) {
1100 if (global.maxpipes != 0) {
1101 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001102 err_code |= ERR_ALERT;
1103 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001104 }
1105 if (*(args[1]) == 0) {
1106 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT | ERR_FATAL;
1108 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001109 }
1110 global.maxpipes = atol(args[1]);
1111 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001112 else if (!strcmp(args[0], "maxzlibmem")) {
1113 if (*(args[1]) == 0) {
1114 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT | ERR_FATAL;
1116 goto out;
1117 }
William Lallemande3a7d992012-11-20 11:25:20 +01001118 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001119 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001120 else if (!strcmp(args[0], "maxcompcpuusage")) {
1121 if (*(args[1]) == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
1125 }
1126 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001127 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001128 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1129 err_code |= ERR_ALERT | ERR_FATAL;
1130 goto out;
1131 }
1132}
1133
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 else if (!strcmp(args[0], "ulimit-n")) {
1135 if (global.rlimit_nofile != 0) {
1136 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001137 err_code |= ERR_ALERT;
1138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 }
1140 if (*(args[1]) == 0) {
1141 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001142 err_code |= ERR_ALERT | ERR_FATAL;
1143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 }
1145 global.rlimit_nofile = atol(args[1]);
1146 }
1147 else if (!strcmp(args[0], "chroot")) {
1148 if (global.chroot != NULL) {
1149 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001150 err_code |= ERR_ALERT;
1151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152 }
1153 if (*(args[1]) == 0) {
1154 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001155 err_code |= ERR_ALERT | ERR_FATAL;
1156 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001157 }
1158 global.chroot = strdup(args[1]);
1159 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001160 else if (!strcmp(args[0], "description")) {
1161 int i, len=0;
1162 char *d;
1163
1164 if (!*args[1]) {
1165 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1166 file, linenum, args[0]);
1167 err_code |= ERR_ALERT | ERR_FATAL;
1168 goto out;
1169 }
1170
Willy Tarreau348acfe2014-04-14 15:00:39 +02001171 for (i = 1; *args[i]; i++)
1172 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001173
1174 if (global.desc)
1175 free(global.desc);
1176
1177 global.desc = d = (char *)calloc(1, len);
1178
Willy Tarreau348acfe2014-04-14 15:00:39 +02001179 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1180 for (i = 2; *args[i]; i++)
1181 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001182 }
1183 else if (!strcmp(args[0], "node")) {
1184 int i;
1185 char c;
1186
1187 for (i=0; args[1][i]; i++) {
1188 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001189 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1190 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001191 break;
1192 }
1193
1194 if (!i || args[1][i]) {
1195 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1196 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1197 file, linenum, args[0]);
1198 err_code |= ERR_ALERT | ERR_FATAL;
1199 goto out;
1200 }
1201
1202 if (global.node)
1203 free(global.node);
1204
1205 global.node = strdup(args[1]);
1206 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001207 else if (!strcmp(args[0], "pidfile")) {
1208 if (global.pidfile != NULL) {
1209 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001210 err_code |= ERR_ALERT;
1211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001212 }
1213 if (*(args[1]) == 0) {
1214 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001215 err_code |= ERR_ALERT | ERR_FATAL;
1216 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001217 }
1218 global.pidfile = strdup(args[1]);
1219 }
Emeric Bruned760922010-10-22 17:59:25 +02001220 else if (!strcmp(args[0], "unix-bind")) {
1221 int cur_arg = 1;
1222 while (*(args[cur_arg])) {
1223 if (!strcmp(args[cur_arg], "prefix")) {
1224 if (global.unix_bind.prefix != NULL) {
1225 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1226 err_code |= ERR_ALERT;
1227 cur_arg += 2;
1228 continue;
1229 }
1230
1231 if (*(args[cur_arg+1]) == 0) {
1232 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1237 cur_arg += 2;
1238 continue;
1239 }
1240
1241 if (!strcmp(args[cur_arg], "mode")) {
1242
1243 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1244 cur_arg += 2;
1245 continue;
1246 }
1247
1248 if (!strcmp(args[cur_arg], "uid")) {
1249
1250 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1251 cur_arg += 2;
1252 continue;
1253 }
1254
1255 if (!strcmp(args[cur_arg], "gid")) {
1256
1257 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1258 cur_arg += 2;
1259 continue;
1260 }
1261
1262 if (!strcmp(args[cur_arg], "user")) {
1263 struct passwd *user;
1264
1265 user = getpwnam(args[cur_arg + 1]);
1266 if (!user) {
1267 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1268 file, linenum, args[0], args[cur_arg + 1 ]);
1269 err_code |= ERR_ALERT | ERR_FATAL;
1270 goto out;
1271 }
1272
1273 global.unix_bind.ux.uid = user->pw_uid;
1274 cur_arg += 2;
1275 continue;
1276 }
1277
1278 if (!strcmp(args[cur_arg], "group")) {
1279 struct group *group;
1280
1281 group = getgrnam(args[cur_arg + 1]);
1282 if (!group) {
1283 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1284 file, linenum, args[0], args[cur_arg + 1 ]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288
1289 global.unix_bind.ux.gid = group->gr_gid;
1290 cur_arg += 2;
1291 continue;
1292 }
1293
Willy Tarreaub48f9582011-09-05 01:17:06 +02001294 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001295 file, linenum, args[0]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299 }
William Lallemand0f99e342011-10-12 17:50:54 +02001300 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1301 /* delete previous herited or defined syslog servers */
1302 struct logsrv *back;
1303 struct logsrv *tmp;
1304
1305 if (*(args[1]) != 0) {
1306 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1307 err_code |= ERR_ALERT | ERR_FATAL;
1308 goto out;
1309 }
1310
1311 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1312 LIST_DEL(&tmp->list);
1313 free(tmp);
1314 }
1315 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001316 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001317 struct sockaddr_storage *sk;
1318 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001319 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001320 int arg = 0;
1321 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001322
Willy Tarreaubaaee002006-06-26 02:48:02 +02001323 if (*(args[1]) == 0 || *(args[2]) == 0) {
1324 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001325 err_code |= ERR_ALERT | ERR_FATAL;
1326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001327 }
William Lallemand0f99e342011-10-12 17:50:54 +02001328
1329 logsrv = calloc(1, sizeof(struct logsrv));
1330
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001331 /* just after the address, a length may be specified */
1332 if (strcmp(args[arg+2], "len") == 0) {
1333 len = atoi(args[arg+3]);
1334 if (len < 80 || len > 65535) {
1335 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1336 file, linenum, args[arg+3]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
1340 logsrv->maxlen = len;
1341
1342 /* skip these two args */
1343 arg += 2;
1344 }
1345 else
1346 logsrv->maxlen = MAX_SYSLOG_LEN;
1347
1348 if (logsrv->maxlen > global.max_syslog_len) {
1349 global.max_syslog_len = logsrv->maxlen;
1350 logline = realloc(logline, global.max_syslog_len + 1);
1351 }
1352
1353 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001354 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001355 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001356 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001357 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 }
1359
William Lallemand0f99e342011-10-12 17:50:54 +02001360 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001361 if (*(args[arg+3])) {
1362 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001363 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001364 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001365 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001366 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 }
1368 }
1369
William Lallemand0f99e342011-10-12 17:50:54 +02001370 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001371 if (*(args[arg+4])) {
1372 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001373 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001374 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001375 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001376 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001377 }
1378 }
1379
Willy Tarreau902636f2013-03-10 19:44:48 +01001380 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001381 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001382 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001383 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001384 free(logsrv);
1385 goto out;
1386 }
1387 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001388
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001389 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001390 if (port1 != port2) {
1391 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1392 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001393 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001394 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001395 goto out;
1396 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001397
William Lallemand0f99e342011-10-12 17:50:54 +02001398 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001399 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001400 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001401 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001402
William Lallemand0f99e342011-10-12 17:50:54 +02001403 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001404 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001405 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1406 char *name;
1407 int len;
1408
1409 if (global.log_send_hostname != NULL) {
1410 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1411 err_code |= ERR_ALERT;
1412 goto out;
1413 }
1414
1415 if (*(args[1]))
1416 name = args[1];
1417 else
1418 name = hostname;
1419
1420 len = strlen(name);
1421
1422 /* We'll add a space after the name to respect the log format */
1423 free(global.log_send_hostname);
1424 global.log_send_hostname = malloc(len + 2);
1425 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1426 }
Kevinm48936af2010-12-22 16:08:21 +00001427 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1428 if (*(args[1]) == 0) {
1429 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
1432 }
1433 free(global.log_tag);
1434 global.log_tag = strdup(args[1]);
1435 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001436 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1437 if (global.spread_checks != 0) {
1438 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001439 err_code |= ERR_ALERT;
1440 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001441 }
1442 if (*(args[1]) == 0) {
1443 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001444 err_code |= ERR_ALERT | ERR_FATAL;
1445 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001446 }
1447 global.spread_checks = atol(args[1]);
1448 if (global.spread_checks < 0 || global.spread_checks > 50) {
1449 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001450 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001451 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001452 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001453 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1454 const char *err;
1455 unsigned int val;
1456
1457
1458 if (*(args[1]) == 0) {
1459 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
1462 }
1463
1464 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1465 if (err) {
1466 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1467 err_code |= ERR_ALERT | ERR_FATAL;
1468 }
1469 global.max_spread_checks = val;
1470 if (global.max_spread_checks < 0) {
1471 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1472 err_code |= ERR_ALERT | ERR_FATAL;
1473 }
1474 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001475 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1476#ifdef USE_CPU_AFFINITY
1477 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001478 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001479 unsigned long cpus = 0;
1480
1481 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001482 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001483 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001484 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001485 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001486 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001487 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001488 proc = atol(args[1]);
1489 if (proc >= 1 && proc <= LONGBITS)
1490 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001491 }
1492
1493 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001494 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",
1495 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001496 err_code |= ERR_ALERT | ERR_FATAL;
1497 goto out;
1498 }
1499
1500 cur_arg = 2;
1501 while (*args[cur_arg]) {
1502 unsigned int low, high;
1503
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001504 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001505 char *dash = strchr(args[cur_arg], '-');
1506
1507 low = high = str2uic(args[cur_arg]);
1508 if (dash)
1509 high = str2uic(dash + 1);
1510
1511 if (high < low) {
1512 unsigned int swap = low;
1513 low = high;
1514 high = swap;
1515 }
1516
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001517 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001518 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001519 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
1522 }
1523
1524 while (low <= high)
1525 cpus |= 1UL << low++;
1526 }
1527 else {
1528 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1529 file, linenum, args[0], args[cur_arg]);
1530 err_code |= ERR_ALERT | ERR_FATAL;
1531 goto out;
1532 }
1533 cur_arg++;
1534 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001535 for (i = 0; i < LONGBITS; i++)
1536 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001537 global.cpu_map[i] = cpus;
1538#else
1539 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
1542#endif
1543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001545 struct cfg_kw_list *kwl;
1546 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001547 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001548
1549 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1550 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1551 if (kwl->kw[index].section != CFG_GLOBAL)
1552 continue;
1553 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001554 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001555 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001556 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001557 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001558 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001559 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001560 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 err_code |= ERR_WARN;
1562 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001563 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001564 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001565 }
1566 }
1567 }
1568
Willy Tarreaubaaee002006-06-26 02:48:02 +02001569 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001571 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001572
Willy Tarreau058e9072009-07-20 09:30:05 +02001573 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001574 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001575 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001576}
1577
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001578void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001579{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001580 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001581 defproxy.mode = PR_MODE_TCP;
1582 defproxy.state = PR_STNEW;
1583 defproxy.maxconn = cfg_maxpconn;
1584 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001585
Simon Horman66183002013-02-23 10:16:43 +09001586 defproxy.defsrv.check.inter = DEF_CHKINTR;
1587 defproxy.defsrv.check.fastinter = 0;
1588 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001589 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1590 defproxy.defsrv.agent.fastinter = 0;
1591 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001592 defproxy.defsrv.check.rise = DEF_RISETIME;
1593 defproxy.defsrv.check.fall = DEF_FALLTIME;
1594 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1595 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001596 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001597 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001598 defproxy.defsrv.maxqueue = 0;
1599 defproxy.defsrv.minconn = 0;
1600 defproxy.defsrv.maxconn = 0;
1601 defproxy.defsrv.slowstart = 0;
1602 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1603 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1604 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001605}
1606
Willy Tarreauade5ec42010-01-28 19:33:49 +01001607
Willy Tarreau63af98d2014-05-18 08:11:41 +02001608/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1609 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1610 * ERR_FATAL in case of error.
1611 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001612static int create_cond_regex_rule(const char *file, int line,
1613 struct proxy *px, int dir, int action, int flags,
1614 const char *cmd, const char *reg, const char *repl,
1615 const char **cond_start)
1616{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001617 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001618 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001619 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001620 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001621 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001622 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001623 int cs;
1624 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001625
1626 if (px == &defproxy) {
1627 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001628 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001629 goto err;
1630 }
1631
1632 if (*reg == 0) {
1633 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001634 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001635 goto err;
1636 }
1637
1638 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001639 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001640
Willy Tarreau5321c422010-01-28 20:35:13 +01001641 if (cond_start &&
1642 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001643 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1644 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1645 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001646 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001647 goto err;
1648 }
1649 }
1650 else if (cond_start && **cond_start) {
1651 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1652 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001653 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001654 goto err;
1655 }
1656
Willy Tarreau63af98d2014-05-18 08:11:41 +02001657 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001658 (dir == SMP_OPT_DIR_REQ) ?
1659 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1660 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1661 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001662
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001663 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001664 if (!preg) {
1665 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001666 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001667 goto err;
1668 }
1669
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001670 cs = !(flags & REG_ICASE);
1671 cap = !(flags & REG_NOSUB);
1672 error = NULL;
1673 if (!regex_comp(reg, preg, cs, cap, &error)) {
1674 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1675 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001677 goto err;
1678 }
1679
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001680 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001681 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682 if (repl && err) {
1683 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1684 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001685 ret_code |= ERR_ALERT | ERR_FATAL;
1686 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001687 }
1688
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001689 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001690 ret_code |= ERR_WARN;
1691
1692 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001693
Willy Tarreau63af98d2014-05-18 08:11:41 +02001694 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001695 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001696 err:
1697 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001698 free(errmsg);
1699 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001700}
1701
Willy Tarreaubaaee002006-06-26 02:48:02 +02001702/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001703 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001704 * Returns the error code, 0 if OK, or any combination of :
1705 * - ERR_ABORT: must abort ASAP
1706 * - ERR_FATAL: we can continue parsing but not start the service
1707 * - ERR_WARN: a warning has been emitted
1708 * - ERR_ALERT: an alert has been emitted
1709 * Only the two first ones can stop processing, the two others are just
1710 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001711 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001712int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1713{
1714 static struct peers *curpeers = NULL;
1715 struct peer *newpeer = NULL;
1716 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001717 struct bind_conf *bind_conf;
1718 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001719 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001720 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001721
1722 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001723 if (!*args[1]) {
1724 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001725 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001726 goto out;
1727 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001728
1729 err = invalid_char(args[1]);
1730 if (err) {
1731 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1732 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001733 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001734 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001735 }
1736
1737 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1738 /*
1739 * If there are two proxies with the same name only following
1740 * combinations are allowed:
1741 */
1742 if (strcmp(curpeers->id, args[1]) == 0) {
1743 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1744 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1745 err_code |= ERR_WARN;
1746 }
1747 }
1748
1749 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1750 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1751 err_code |= ERR_ALERT | ERR_ABORT;
1752 goto out;
1753 }
1754
1755 curpeers->next = peers;
1756 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001757 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001758 curpeers->conf.line = linenum;
1759 curpeers->last_change = now.tv_sec;
1760 curpeers->id = strdup(args[1]);
Willy Tarreau34d05b02015-05-01 20:02:17 +02001761 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001762 }
1763 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001764 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001765 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001766 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001767
1768 if (!*args[2]) {
1769 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1770 file, linenum, args[0]);
1771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
1773 }
1774
1775 err = invalid_char(args[1]);
1776 if (err) {
1777 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1778 file, linenum, *err, args[1]);
1779 err_code |= ERR_ALERT | ERR_FATAL;
1780 goto out;
1781 }
1782
1783 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1784 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1785 err_code |= ERR_ALERT | ERR_ABORT;
1786 goto out;
1787 }
1788
1789 /* the peers are linked backwards first */
1790 curpeers->count++;
1791 newpeer->next = curpeers->remote;
1792 curpeers->remote = newpeer;
1793 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001794 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001795 newpeer->conf.line = linenum;
1796
1797 newpeer->last_change = now.tv_sec;
1798 newpeer->id = strdup(args[1]);
1799
Willy Tarreau902636f2013-03-10 19:44:48 +01001800 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001801 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001802 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001805 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001806
1807 proto = protocol_by_family(sk->ss_family);
1808 if (!proto || !proto->connect) {
1809 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1810 file, linenum, args[0], args[1]);
1811 err_code |= ERR_ALERT | ERR_FATAL;
1812 goto out;
1813 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001814
1815 if (port1 != port2) {
1816 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1817 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001818 err_code |= ERR_ALERT | ERR_FATAL;
1819 goto out;
1820 }
1821
Willy Tarreau2aa38802013-02-20 19:20:59 +01001822 if (!port1) {
1823 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1824 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001828
Emeric Brun32da3c42010-09-23 18:39:19 +02001829 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001830 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001831 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001832 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001833
Emeric Brun32da3c42010-09-23 18:39:19 +02001834 if (strcmp(newpeer->id, localpeer) == 0) {
1835 /* Current is local peer, it define a frontend */
1836 newpeer->local = 1;
1837
1838 if (!curpeers->peers_fe) {
1839 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1840 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1841 err_code |= ERR_ALERT | ERR_ABORT;
1842 goto out;
1843 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001844
Willy Tarreau237250c2011-07-29 01:49:03 +02001845 init_new_proxy(curpeers->peers_fe);
1846 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001847
1848 curpeers->peers_fe->last_change = now.tv_sec;
1849 curpeers->peers_fe->id = strdup(args[1]);
1850 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001851 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001852 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001853 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001854 curpeers->peers_fe->accept = peer_accept;
1855 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001856 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1857 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreaucdb5e922015-05-01 19:12:05 +02001858 curpeers->peers_fe->bind_proc = 0; /* will be filled by users */
Willy Tarreau4348fad2012-09-20 16:48:07 +02001859
1860 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1861
Willy Tarreau902636f2013-03-10 19:44:48 +01001862 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1863 if (errmsg && *errmsg) {
1864 indent_msg(&errmsg, 2);
1865 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001866 }
1867 else
1868 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1869 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001870 err_code |= ERR_FATAL;
1871 goto out;
1872 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001873
1874 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001875 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001876 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1877 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1878 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1879 l->accept = session_accept;
1880 l->handler = process_session;
1881 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1882 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1883 global.maxsock += l->maxconn;
1884 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001885 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001886 else {
1887 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1888 file, linenum, args[0], args[1],
1889 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1890 err_code |= ERR_FATAL;
1891 goto out;
1892 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001893 }
1894 } /* neither "peer" nor "peers" */
Willy Tarreau34d05b02015-05-01 20:02:17 +02001895 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
1896 curpeers->state = PR_STSTOPPED;
1897 }
1898 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
1899 curpeers->state = PR_STNEW;
1900 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001901 else if (*args[0] != 0) {
1902 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1903 err_code |= ERR_ALERT | ERR_FATAL;
1904 goto out;
1905 }
1906
1907out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001908 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001909 return err_code;
1910}
1911
Willy Tarreau3842f002009-06-14 11:39:52 +02001912int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913{
1914 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001915 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001916 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001917 int rc;
1918 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001919 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001920 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001921 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001922 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001923 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001924
Willy Tarreau977b8e42006-12-29 14:19:17 +01001925 if (!strcmp(args[0], "listen"))
1926 rc = PR_CAP_LISTEN;
1927 else if (!strcmp(args[0], "frontend"))
1928 rc = PR_CAP_FE | PR_CAP_RS;
1929 else if (!strcmp(args[0], "backend"))
1930 rc = PR_CAP_BE | PR_CAP_RS;
1931 else if (!strcmp(args[0], "ruleset"))
1932 rc = PR_CAP_RS;
1933 else
1934 rc = PR_CAP_NONE;
1935
1936 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001937 struct ebpt_node *node;
1938
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 if (!*args[1]) {
1940 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1941 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001943 err_code |= ERR_ALERT | ERR_ABORT;
1944 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001946
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001947 err = invalid_char(args[1]);
1948 if (err) {
1949 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1950 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001951 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001952 }
1953
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001954 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1955 curproxy = container_of(node, struct proxy, conf.by_name);
1956
1957 if (strcmp(curproxy->id, args[1]) != 0)
1958 break;
1959
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001960 /*
1961 * If there are two proxies with the same name only following
1962 * combinations are allowed:
1963 *
1964 * listen backend frontend ruleset
1965 * listen - - - -
1966 * backend - - OK -
1967 * frontend - OK - -
1968 * ruleset - - - -
1969 */
1970
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001971 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1972 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001973 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1974 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1975 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001976 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001977 }
1978 }
1979
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1981 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001982 err_code |= ERR_ALERT | ERR_ABORT;
1983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001984 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001985
Willy Tarreau97cb7802010-01-03 20:23:58 +01001986 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001987 curproxy->next = proxy;
1988 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001989 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1990 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001991 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001992 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001993 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001994 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995
1996 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001997 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001998 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001999
Willy Tarreau4348fad2012-09-20 16:48:07 +02002000 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2001
Willy Tarreau902636f2013-03-10 19:44:48 +01002002 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2003 if (errmsg && *errmsg) {
2004 indent_msg(&errmsg, 2);
2005 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002006 }
2007 else
2008 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2009 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002010 err_code |= ERR_FATAL;
2011 goto out;
2012 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002013
Willy Tarreau4348fad2012-09-20 16:48:07 +02002014 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002015 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002016 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002017 }
2018
2019 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002020 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002021 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002022
Willy Tarreaubaaee002006-06-26 02:48:02 +02002023 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002024 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002025 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002026 curproxy->no_options = defproxy.no_options;
2027 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002028 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002029 curproxy->except_net = defproxy.except_net;
2030 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002031 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002032 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002033
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002034 if (defproxy.fwdfor_hdr_len) {
2035 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2036 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2037 }
2038
Willy Tarreaub86db342009-11-30 11:50:16 +01002039 if (defproxy.orgto_hdr_len) {
2040 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2041 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2042 }
2043
Mark Lamourinec2247f02012-01-04 13:02:01 -05002044 if (defproxy.server_id_hdr_len) {
2045 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2046 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2047 }
2048
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049 if (curproxy->cap & PR_CAP_FE) {
2050 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002051 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002052 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002053
2054 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002055 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2056 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002057
2058 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2059 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002060
Willy Tarreau977b8e42006-12-29 14:19:17 +01002061 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002062 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002063 curproxy->fullconn = defproxy.fullconn;
2064 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002065 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002067 if (defproxy.check_req) {
2068 curproxy->check_req = calloc(1, defproxy.check_len);
2069 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2070 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002071 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002073 if (defproxy.expect_str) {
2074 curproxy->expect_str = strdup(defproxy.expect_str);
2075 if (defproxy.expect_regex) {
2076 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002077 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2078 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002079 }
2080 }
2081
Willy Tarreau67402132012-05-31 20:40:20 +02002082 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002083 if (defproxy.cookie_name)
2084 curproxy->cookie_name = strdup(defproxy.cookie_name);
2085 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002086 if (defproxy.cookie_domain)
2087 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002088
Willy Tarreau31936852010-10-06 16:59:56 +02002089 if (defproxy.cookie_maxidle)
2090 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2091
2092 if (defproxy.cookie_maxlife)
2093 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2094
Emeric Brun647caf12009-06-30 17:57:00 +02002095 if (defproxy.rdp_cookie_name)
2096 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2097 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2098
Willy Tarreau01732802007-11-01 22:48:15 +01002099 if (defproxy.url_param_name)
2100 curproxy->url_param_name = strdup(defproxy.url_param_name);
2101 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002102
Benoitaffb4812009-03-25 13:02:10 +01002103 if (defproxy.hh_name)
2104 curproxy->hh_name = strdup(defproxy.hh_name);
2105 curproxy->hh_len = defproxy.hh_len;
2106 curproxy->hh_match_domain = defproxy.hh_match_domain;
2107
Willy Tarreauef9a3602012-12-08 22:29:20 +01002108 if (defproxy.conn_src.iface_name)
2109 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2110 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002111 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002112#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002113 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002114#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002117 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002118 if (defproxy.capture_name)
2119 curproxy->capture_name = strdup(defproxy.capture_name);
2120 curproxy->capture_namelen = defproxy.capture_namelen;
2121 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002122 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002123
Willy Tarreau977b8e42006-12-29 14:19:17 +01002124 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002125 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002126 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002127 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002128 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002129 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002130 curproxy->mon_net = defproxy.mon_net;
2131 curproxy->mon_mask = defproxy.mon_mask;
2132 if (defproxy.monitor_uri)
2133 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2134 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002135 if (defproxy.defbe.name)
2136 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002137
2138 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002139 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2140 if (curproxy->conf.logformat_string &&
2141 curproxy->conf.logformat_string != default_http_log_format &&
2142 curproxy->conf.logformat_string != default_tcp_log_format &&
2143 curproxy->conf.logformat_string != clf_http_log_format)
2144 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2145
2146 if (defproxy.conf.lfs_file) {
2147 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2148 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2149 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002150 }
2151
2152 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002153 curproxy->timeout.connect = defproxy.timeout.connect;
2154 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002155 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002156 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002157 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002158 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002159 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002160 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002161 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002162 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002163 }
2164
Willy Tarreaubaaee002006-06-26 02:48:02 +02002165 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002166 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002167
2168 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002169 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002170 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002171 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002172 LIST_INIT(&node->list);
2173 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2174 }
2175
Willy Tarreau62a61232013-04-12 18:13:46 +02002176 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2177 if (curproxy->conf.uniqueid_format_string)
2178 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2179
2180 if (defproxy.conf.uif_file) {
2181 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2182 curproxy->conf.uif_line = defproxy.conf.uif_line;
2183 }
William Lallemanda73203e2012-03-12 12:48:57 +01002184
2185 /* copy default header unique id */
2186 if (defproxy.header_unique_id)
2187 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2188
William Lallemand82fe75c2012-10-23 10:25:10 +02002189 /* default compression options */
2190 if (defproxy.comp != NULL) {
2191 curproxy->comp = calloc(1, sizeof(struct comp));
2192 curproxy->comp->algos = defproxy.comp->algos;
2193 curproxy->comp->types = defproxy.comp->types;
2194 }
2195
Willy Tarreaubaaee002006-06-26 02:48:02 +02002196 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002197 curproxy->conf.used_listener_id = EB_ROOT;
2198 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002199
Willy Tarreau93893792009-07-23 13:19:11 +02002200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002201 }
2202 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2203 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002204 /* FIXME-20070101: we should do this too at the end of the
2205 * config parsing to free all default values.
2206 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002207 free(defproxy.check_req);
2208 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002209 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002210 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002211 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002212 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002213 free(defproxy.capture_name);
2214 free(defproxy.monitor_uri);
2215 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002216 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002217 free(defproxy.fwdfor_hdr_name);
2218 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002219 free(defproxy.orgto_hdr_name);
2220 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002221 free(defproxy.server_id_hdr_name);
2222 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002223 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002224 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002225 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002226 free(defproxy.expect_regex);
2227 defproxy.expect_regex = NULL;
2228 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002229
Willy Tarreau62a61232013-04-12 18:13:46 +02002230 if (defproxy.conf.logformat_string != default_http_log_format &&
2231 defproxy.conf.logformat_string != default_tcp_log_format &&
2232 defproxy.conf.logformat_string != clf_http_log_format)
2233 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002234
Willy Tarreau62a61232013-04-12 18:13:46 +02002235 free(defproxy.conf.uniqueid_format_string);
2236 free(defproxy.conf.lfs_file);
2237 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002238
Willy Tarreaua534fea2008-08-03 12:19:50 +02002239 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002240 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002241
Willy Tarreaubaaee002006-06-26 02:48:02 +02002242 /* we cannot free uri_auth because it might already be used */
2243 init_default_instance();
2244 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002245 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2246 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002247 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002249 }
2250 else if (curproxy == NULL) {
2251 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002252 err_code |= ERR_ALERT | ERR_FATAL;
2253 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002254 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002255
2256 /* update the current file and line being parsed */
2257 curproxy->conf.args.file = curproxy->conf.file;
2258 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002259
2260 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002261 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2262 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2263 if (err_code & ERR_FATAL)
2264 goto out;
2265 }
2266 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002267 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002268 int cur_arg;
2269
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270 if (curproxy == &defproxy) {
2271 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002272 err_code |= ERR_ALERT | ERR_FATAL;
2273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002274 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002275 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002276 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277
Willy Tarreau24709282013-03-10 21:32:12 +01002278 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002279 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002280 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002283 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002284
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002285 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002286
2287 /* use default settings for unix sockets */
2288 bind_conf->ux.uid = global.unix_bind.ux.uid;
2289 bind_conf->ux.gid = global.unix_bind.ux.gid;
2290 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002291
2292 /* NOTE: the following line might create several listeners if there
2293 * are comma-separated IPs or port ranges. So all further processing
2294 * will have to be applied to all listeners created after last_listen.
2295 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002296 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2297 if (errmsg && *errmsg) {
2298 indent_msg(&errmsg, 2);
2299 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002300 }
2301 else
2302 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2303 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
2306 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002307
Willy Tarreau4348fad2012-09-20 16:48:07 +02002308 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2309 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002310 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002311 }
2312
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002313 cur_arg = 2;
2314 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002315 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002316 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002317 char *err;
2318
Willy Tarreau26982662012-09-12 23:17:10 +02002319 kw = bind_find_kw(args[cur_arg]);
2320 if (kw) {
2321 char *err = NULL;
2322 int code;
2323
2324 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002325 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2326 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002327 cur_arg += 1 + kw->skip ;
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331
Willy Tarreau4348fad2012-09-20 16:48:07 +02002332 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002333 err_code |= code;
2334
2335 if (code) {
2336 if (err && *err) {
2337 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002338 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002339 }
2340 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002341 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2342 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002343 if (code & ERR_FATAL) {
2344 free(err);
2345 cur_arg += 1 + kw->skip;
2346 goto out;
2347 }
2348 }
2349 free(err);
2350 cur_arg += 1 + kw->skip;
2351 continue;
2352 }
2353
Willy Tarreau8638f482012-09-18 18:01:17 +02002354 err = NULL;
2355 if (!bind_dumped) {
2356 bind_dump_kws(&err);
2357 indent_msg(&err, 4);
2358 bind_dumped = 1;
2359 }
2360
2361 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2362 file, linenum, args[0], args[1], args[cur_arg],
2363 err ? " Registered keywords :" : "", err ? err : "");
2364 free(err);
2365
Willy Tarreau93893792009-07-23 13:19:11 +02002366 err_code |= ERR_ALERT | ERR_FATAL;
2367 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002368 }
Willy Tarreau93893792009-07-23 13:19:11 +02002369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002370 }
2371 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002372 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2374 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002378 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002379 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002380
Willy Tarreaubaaee002006-06-26 02:48:02 +02002381 /* flush useless bits */
2382 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002383 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002384 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002385 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002386 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002387 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002388
Willy Tarreau1c47f852006-07-09 08:22:27 +02002389 if (!*args[1]) {
2390 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2391 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002392 err_code |= ERR_ALERT | ERR_FATAL;
2393 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002394 }
2395
Willy Tarreaua534fea2008-08-03 12:19:50 +02002396 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002397 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002398 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002399 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002400 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2401
Willy Tarreau93893792009-07-23 13:19:11 +02002402 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002403 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002404 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2405 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2406 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2407 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2408 else {
2409 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002410 err_code |= ERR_ALERT | ERR_FATAL;
2411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002412 }
2413 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002414 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002415 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002416
2417 if (curproxy == &defproxy) {
2418 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2419 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002420 err_code |= ERR_ALERT | ERR_FATAL;
2421 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002422 }
2423
2424 if (!*args[1]) {
2425 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2426 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002429 }
2430
2431 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002432 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002433
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002434 if (curproxy->uuid <= 0) {
2435 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002436 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002439 }
2440
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002441 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2442 if (node) {
2443 struct proxy *target = container_of(node, struct proxy, conf.id);
2444 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2445 file, linenum, proxy_type_str(curproxy), curproxy->id,
2446 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002451 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002452 else if (!strcmp(args[0], "description")) {
2453 int i, len=0;
2454 char *d;
2455
Cyril Bonté99ed3272010-01-24 23:29:44 +01002456 if (curproxy == &defproxy) {
2457 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2458 file, linenum, args[0]);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002463 if (!*args[1]) {
2464 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2465 file, linenum, args[0]);
2466 return -1;
2467 }
2468
Willy Tarreau348acfe2014-04-14 15:00:39 +02002469 for (i = 1; *args[i]; i++)
2470 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002471
2472 d = (char *)calloc(1, len);
2473 curproxy->desc = d;
2474
Willy Tarreau348acfe2014-04-14 15:00:39 +02002475 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2476 for (i = 2; *args[i]; i++)
2477 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002478
2479 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002480 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2481 curproxy->state = PR_STSTOPPED;
2482 }
2483 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2484 curproxy->state = PR_STNEW;
2485 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002486 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2487 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002488 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002489
2490 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002491 unsigned int low, high;
2492
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002493 if (strcmp(args[cur_arg], "all") == 0) {
2494 set = 0;
2495 break;
2496 }
2497 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002498 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002499 }
2500 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002501 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002502 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002503 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002504 char *dash = strchr(args[cur_arg], '-');
2505
2506 low = high = str2uic(args[cur_arg]);
2507 if (dash)
2508 high = str2uic(dash + 1);
2509
2510 if (high < low) {
2511 unsigned int swap = low;
2512 low = high;
2513 high = swap;
2514 }
2515
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002516 if (low < 1 || high > LONGBITS) {
2517 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2518 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_FATAL;
2520 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002521 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002522 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002523 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002524 }
2525 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002526 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2527 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002528 err_code |= ERR_ALERT | ERR_FATAL;
2529 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002530 }
2531 cur_arg++;
2532 }
2533 curproxy->bind_proc = set;
2534 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002535 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002536 if (curproxy == &defproxy) {
2537 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_ALERT | ERR_FATAL;
2539 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002540 }
2541
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002542 err = invalid_char(args[1]);
2543 if (err) {
2544 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2545 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002546 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002547 }
2548
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002549 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002550 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2551 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002552 err_code |= ERR_ALERT | ERR_FATAL;
2553 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002554 }
2555 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2557 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558
Willy Tarreau977b8e42006-12-29 14:19:17 +01002559 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002560 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561
Willy Tarreaubaaee002006-06-26 02:48:02 +02002562 if (*(args[1]) == 0) {
2563 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2564 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002565 err_code |= ERR_ALERT | ERR_FATAL;
2566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002568
Willy Tarreau67402132012-05-31 20:40:20 +02002569 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002570 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002571 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002572 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002573 curproxy->cookie_name = strdup(args[1]);
2574 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002575
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 cur_arg = 2;
2577 while (*(args[cur_arg])) {
2578 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002579 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 }
2581 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002582 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002583 }
2584 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002585 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 }
2587 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002588 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002589 }
2590 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002591 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002592 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002593 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002594 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002595 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002597 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002598 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002599 else if (!strcmp(args[cur_arg], "httponly")) {
2600 curproxy->ck_opts |= PR_CK_HTTPONLY;
2601 }
2602 else if (!strcmp(args[cur_arg], "secure")) {
2603 curproxy->ck_opts |= PR_CK_SECURE;
2604 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002605 else if (!strcmp(args[cur_arg], "domain")) {
2606 if (!*args[cur_arg + 1]) {
2607 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2608 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002611 }
2612
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002613 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002614 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002615 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2616 " dots nor does not start with a dot."
2617 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002618 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002619 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002620 }
2621
2622 err = invalid_domainchar(args[cur_arg + 1]);
2623 if (err) {
2624 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2625 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002626 err_code |= ERR_ALERT | ERR_FATAL;
2627 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002628 }
2629
Willy Tarreau68a897b2009-12-03 23:28:34 +01002630 if (!curproxy->cookie_domain) {
2631 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2632 } else {
2633 /* one domain was already specified, add another one by
2634 * building the string which will be returned along with
2635 * the cookie.
2636 */
2637 char *new_ptr;
2638 int new_len = strlen(curproxy->cookie_domain) +
2639 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2640 new_ptr = malloc(new_len);
2641 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2642 free(curproxy->cookie_domain);
2643 curproxy->cookie_domain = new_ptr;
2644 }
Willy Tarreau31936852010-10-06 16:59:56 +02002645 cur_arg++;
2646 }
2647 else if (!strcmp(args[cur_arg], "maxidle")) {
2648 unsigned int maxidle;
2649 const char *res;
2650
2651 if (!*args[cur_arg + 1]) {
2652 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2653 file, linenum, args[cur_arg]);
2654 err_code |= ERR_ALERT | ERR_FATAL;
2655 goto out;
2656 }
2657
2658 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2659 if (res) {
2660 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2661 file, linenum, *res, args[cur_arg]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665 curproxy->cookie_maxidle = maxidle;
2666 cur_arg++;
2667 }
2668 else if (!strcmp(args[cur_arg], "maxlife")) {
2669 unsigned int maxlife;
2670 const char *res;
2671
2672 if (!*args[cur_arg + 1]) {
2673 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2674 file, linenum, args[cur_arg]);
2675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
2677 }
2678
2679 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2680 if (res) {
2681 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2682 file, linenum, *res, args[cur_arg]);
2683 err_code |= ERR_ALERT | ERR_FATAL;
2684 goto out;
2685 }
2686 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002687 cur_arg++;
2688 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002689 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002690 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 +02002691 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002692 err_code |= ERR_ALERT | ERR_FATAL;
2693 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002694 }
2695 cur_arg++;
2696 }
Willy Tarreau67402132012-05-31 20:40:20 +02002697 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002698 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2699 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002700 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002701 }
2702
Willy Tarreau67402132012-05-31 20:40:20 +02002703 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002704 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2705 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002706 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002707 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002708
Willy Tarreau67402132012-05-31 20:40:20 +02002709 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002710 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2711 file, linenum);
2712 err_code |= ERR_ALERT | ERR_FATAL;
2713 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002715 else if (!strcmp(args[0], "persist")) { /* persist */
2716 if (*(args[1]) == 0) {
2717 Alert("parsing [%s:%d] : missing persist method.\n",
2718 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002719 err_code |= ERR_ALERT | ERR_FATAL;
2720 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002721 }
2722
2723 if (!strncmp(args[1], "rdp-cookie", 10)) {
2724 curproxy->options2 |= PR_O2_RDPC_PRST;
2725
Emeric Brunb982a3d2010-01-04 15:45:53 +01002726 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002727 const char *beg, *end;
2728
2729 beg = args[1] + 11;
2730 end = strchr(beg, ')');
2731
2732 if (!end || end == beg) {
2733 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2734 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002737 }
2738
2739 free(curproxy->rdp_cookie_name);
2740 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2741 curproxy->rdp_cookie_len = end-beg;
2742 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002743 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002744 free(curproxy->rdp_cookie_name);
2745 curproxy->rdp_cookie_name = strdup("msts");
2746 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2747 }
2748 else { /* syntax */
2749 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2750 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002751 err_code |= ERR_ALERT | ERR_FATAL;
2752 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002753 }
2754 }
2755 else {
2756 Alert("parsing [%s:%d] : unknown persist method.\n",
2757 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002758 err_code |= ERR_ALERT | ERR_FATAL;
2759 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002760 }
2761 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002763 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002765 if (curproxy == &defproxy) {
2766 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
2769 }
2770
Willy Tarreau977b8e42006-12-29 14:19:17 +01002771 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002772 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002773
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002775 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002777 err_code |= ERR_ALERT | ERR_FATAL;
2778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 }
2780 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002781 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 curproxy->appsession_name = strdup(args[1]);
2783 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2784 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002785 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2786 if (err) {
2787 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2788 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002789 err_code |= ERR_ALERT | ERR_FATAL;
2790 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002791 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002792 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002793
Willy Tarreau51041c72007-09-09 21:56:53 +02002794 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2795 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002796 err_code |= ERR_ALERT | ERR_ABORT;
2797 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002798 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002799
2800 cur_arg = 6;
2801 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002802 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2803 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002804 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002805 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002806 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002807 } else if (!strcmp(args[cur_arg], "prefix")) {
2808 curproxy->options2 |= PR_O2_AS_PFX;
2809 } else if (!strcmp(args[cur_arg], "mode")) {
2810 if (!*args[cur_arg + 1]) {
2811 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2812 file, linenum, args[0], args[cur_arg]);
2813 err_code |= ERR_ALERT | ERR_FATAL;
2814 goto out;
2815 }
2816
2817 cur_arg++;
2818 if (!strcmp(args[cur_arg], "query-string")) {
2819 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2820 curproxy->options2 |= PR_O2_AS_M_QS;
2821 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2822 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2823 curproxy->options2 |= PR_O2_AS_M_PP;
2824 } else {
2825 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2826 err_code |= ERR_ALERT | ERR_FATAL;
2827 goto out;
2828 }
2829 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002830 cur_arg++;
2831 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 } /* Url App Session */
2833 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002834 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002835 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002836
Willy Tarreaubaaee002006-06-26 02:48:02 +02002837 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002838 if (curproxy == &defproxy) {
2839 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
2842 }
2843
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 if (*(args[4]) == 0) {
2845 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2846 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002847 err_code |= ERR_ALERT | ERR_FATAL;
2848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002849 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002850 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002851 curproxy->capture_name = strdup(args[2]);
2852 curproxy->capture_namelen = strlen(curproxy->capture_name);
2853 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002854 curproxy->to_log |= LW_COOKIE;
2855 }
2856 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2857 struct cap_hdr *hdr;
2858
2859 if (curproxy == &defproxy) {
2860 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 +02002861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002863 }
2864
2865 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2866 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2867 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
2871
2872 hdr = calloc(sizeof(struct cap_hdr), 1);
2873 hdr->next = curproxy->req_cap;
2874 hdr->name = strdup(args[3]);
2875 hdr->namelen = strlen(args[3]);
2876 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002877 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002878 hdr->index = curproxy->nb_req_cap++;
2879 curproxy->req_cap = hdr;
2880 curproxy->to_log |= LW_REQHDR;
2881 }
2882 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2883 struct cap_hdr *hdr;
2884
2885 if (curproxy == &defproxy) {
2886 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 +02002887 err_code |= ERR_ALERT | ERR_FATAL;
2888 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }
2890
2891 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2892 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2893 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 }
2897 hdr = calloc(sizeof(struct cap_hdr), 1);
2898 hdr->next = curproxy->rsp_cap;
2899 hdr->name = strdup(args[3]);
2900 hdr->namelen = strlen(args[3]);
2901 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002902 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002903 hdr->index = curproxy->nb_rsp_cap++;
2904 curproxy->rsp_cap = hdr;
2905 curproxy->to_log |= LW_RSPHDR;
2906 }
2907 else {
2908 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2909 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 }
2913 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002914 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002915 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002916 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002917
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 if (*(args[1]) == 0) {
2919 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002921 err_code |= ERR_ALERT | ERR_FATAL;
2922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002923 }
2924 curproxy->conn_retries = atol(args[1]);
2925 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002926 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002927 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002928
2929 if (curproxy == &defproxy) {
2930 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2931 err_code |= ERR_ALERT | ERR_FATAL;
2932 goto out;
2933 }
2934
Willy Tarreau20b0de52012-12-24 15:45:22 +01002935 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2936 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2937 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2938 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002939 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002940 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2941 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 +01002942 file, linenum, args[0]);
2943 err_code |= ERR_WARN;
2944 }
2945
Willy Tarreauff011f22011-01-06 17:51:27 +01002946 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002947
Willy Tarreauff011f22011-01-06 17:51:27 +01002948 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002949 err_code |= ERR_ALERT | ERR_ABORT;
2950 goto out;
2951 }
2952
Willy Tarreau5002f572014-04-23 01:32:02 +02002953 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002954 err_code |= warnif_cond_conflicts(rule->cond,
2955 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2956 file, linenum);
2957
Willy Tarreauff011f22011-01-06 17:51:27 +01002958 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002959 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002960 else if (!strcmp(args[0], "http-response")) { /* response access control */
2961 struct http_res_rule *rule;
2962
2963 if (curproxy == &defproxy) {
2964 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
2967 }
2968
2969 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2970 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2971 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2972 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2973 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2974 file, linenum, args[0]);
2975 err_code |= ERR_WARN;
2976 }
2977
2978 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2979
2980 if (!rule) {
2981 err_code |= ERR_ALERT | ERR_ABORT;
2982 goto out;
2983 }
2984
2985 err_code |= warnif_cond_conflicts(rule->cond,
2986 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2987 file, linenum);
2988
2989 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2990 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002991 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2992 /* set the header name and length into the proxy structure */
2993 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2994 err_code |= ERR_WARN;
2995
2996 if (!*args[1]) {
2997 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2998 file, linenum, args[0]);
2999 err_code |= ERR_ALERT | ERR_FATAL;
3000 goto out;
3001 }
3002
3003 /* set the desired header name */
3004 free(curproxy->server_id_hdr_name);
3005 curproxy->server_id_hdr_name = strdup(args[1]);
3006 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3007 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003008 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003009 struct http_req_rule *rule;
3010
Willy Tarreaub099aca2008-10-12 17:26:37 +02003011 if (curproxy == &defproxy) {
3012 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003013 err_code |= ERR_ALERT | ERR_FATAL;
3014 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003015 }
3016
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003017 /* emulate "block" using "http-request block". Since these rules are supposed to
3018 * be processed before all http-request rules, we put them into their own list
3019 * and will insert them at the end.
3020 */
3021 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3022 if (!rule) {
3023 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003024 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003025 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003026 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3027 err_code |= warnif_cond_conflicts(rule->cond,
3028 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3029 file, linenum);
3030 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003031
3032 if (!already_warned(WARN_BLOCK_DEPRECATED))
3033 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]);
3034
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003035 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003036 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003037 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003038
Cyril Bonté99ed3272010-01-24 23:29:44 +01003039 if (curproxy == &defproxy) {
3040 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
3043 }
3044
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003045 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003046 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3047 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_ALERT | ERR_FATAL;
3049 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003050 }
3051
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003052 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003053 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003054 err_code |= warnif_cond_conflicts(rule->cond,
3055 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3056 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003057 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003058 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003059 struct switching_rule *rule;
3060
Willy Tarreaub099aca2008-10-12 17:26:37 +02003061 if (curproxy == &defproxy) {
3062 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003063 err_code |= ERR_ALERT | ERR_FATAL;
3064 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003065 }
3066
Willy Tarreau55ea7572007-06-17 19:56:27 +02003067 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003068 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003069
3070 if (*(args[1]) == 0) {
3071 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003074 }
3075
Willy Tarreauf51658d2014-04-23 01:21:56 +02003076 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3077 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3078 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3079 file, linenum, errmsg);
3080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
3082 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003083
Willy Tarreauf51658d2014-04-23 01:21:56 +02003084 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003085 }
3086
3087 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3088 rule->cond = cond;
3089 rule->be.name = strdup(args[1]);
3090 LIST_INIT(&rule->list);
3091 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3092 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003093 else if (strcmp(args[0], "use-server") == 0) {
3094 struct server_rule *rule;
3095
3096 if (curproxy == &defproxy) {
3097 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3098 err_code |= ERR_ALERT | ERR_FATAL;
3099 goto out;
3100 }
3101
3102 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3103 err_code |= ERR_WARN;
3104
3105 if (*(args[1]) == 0) {
3106 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3107 err_code |= ERR_ALERT | ERR_FATAL;
3108 goto out;
3109 }
3110
3111 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3112 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3113 file, linenum, args[0]);
3114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
3116 }
3117
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003118 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3119 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3120 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003121 err_code |= ERR_ALERT | ERR_FATAL;
3122 goto out;
3123 }
3124
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003125 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003126
3127 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3128 rule->cond = cond;
3129 rule->srv.name = strdup(args[1]);
3130 LIST_INIT(&rule->list);
3131 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3132 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3133 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003134 else if ((!strcmp(args[0], "force-persist")) ||
3135 (!strcmp(args[0], "ignore-persist"))) {
3136 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003137
3138 if (curproxy == &defproxy) {
3139 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3140 err_code |= ERR_ALERT | ERR_FATAL;
3141 goto out;
3142 }
3143
3144 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3145 err_code |= ERR_WARN;
3146
Willy Tarreauef6494c2010-01-28 17:12:36 +01003147 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003148 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3149 file, linenum, args[0]);
3150 err_code |= ERR_ALERT | ERR_FATAL;
3151 goto out;
3152 }
3153
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003154 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3155 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3156 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003157 err_code |= ERR_ALERT | ERR_FATAL;
3158 goto out;
3159 }
3160
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003161 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3162 * where force-persist is applied.
3163 */
3164 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003165
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003166 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003167 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003168 if (!strcmp(args[0], "force-persist")) {
3169 rule->type = PERSIST_TYPE_FORCE;
3170 } else {
3171 rule->type = PERSIST_TYPE_IGNORE;
3172 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003173 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003174 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003175 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003176 else if (!strcmp(args[0], "stick-table")) {
3177 int myidx = 1;
3178
Emeric Brun32da3c42010-09-23 18:39:19 +02003179 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003180 curproxy->table.type = (unsigned int)-1;
3181 while (*args[myidx]) {
3182 const char *err;
3183
3184 if (strcmp(args[myidx], "size") == 0) {
3185 myidx++;
3186 if (!*(args[myidx])) {
3187 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3188 file, linenum, args[myidx-1]);
3189 err_code |= ERR_ALERT | ERR_FATAL;
3190 goto out;
3191 }
3192 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3193 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3194 file, linenum, *err, args[myidx-1]);
3195 err_code |= ERR_ALERT | ERR_FATAL;
3196 goto out;
3197 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003198 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003199 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003200 else if (strcmp(args[myidx], "peers") == 0) {
3201 myidx++;
Godbach50523162013-12-11 19:48:57 +08003202 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003203 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3204 file, linenum, args[myidx-1]);
3205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Godbach50523162013-12-11 19:48:57 +08003207 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003208 curproxy->table.peers.name = strdup(args[myidx++]);
3209 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003210 else if (strcmp(args[myidx], "expire") == 0) {
3211 myidx++;
3212 if (!*(args[myidx])) {
3213 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3214 file, linenum, args[myidx-1]);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
3218 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3219 if (err) {
3220 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3221 file, linenum, *err, args[myidx-1]);
3222 err_code |= ERR_ALERT | ERR_FATAL;
3223 goto out;
3224 }
Ben Cabot85a1c182016-01-20 09:44:39 +00003225 if (val > INT_MAX) {
3226 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
3227 file, linenum, val);
3228 err_code |= ERR_ALERT | ERR_FATAL;
3229 goto out;
3230 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003231 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003232 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003233 }
3234 else if (strcmp(args[myidx], "nopurge") == 0) {
3235 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003236 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003237 }
3238 else if (strcmp(args[myidx], "type") == 0) {
3239 myidx++;
3240 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3241 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3242 file, linenum, args[myidx]);
3243 err_code |= ERR_ALERT | ERR_FATAL;
3244 goto out;
3245 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003246 /* myidx already points to next arg */
3247 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003248 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003249 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003250 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003251
3252 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003253 nw = args[myidx];
3254 while (*nw) {
3255 /* the "store" keyword supports a comma-separated list */
3256 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003257 sa = NULL; /* store arg */
3258 while (*nw && *nw != ',') {
3259 if (*nw == '(') {
3260 *nw = 0;
3261 sa = ++nw;
3262 while (*nw != ')') {
3263 if (!*nw) {
3264 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3265 file, linenum, args[0], cw);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
3269 nw++;
3270 }
3271 *nw = '\0';
3272 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003273 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003274 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003275 if (*nw)
3276 *nw++ = '\0';
3277 type = stktable_get_data_type(cw);
3278 if (type < 0) {
3279 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3280 file, linenum, args[0], cw);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283 }
Willy Tarreauac782882010-06-20 10:41:54 +02003284
3285 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3286 switch (err) {
3287 case PE_NONE: break;
3288 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003289 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3290 file, linenum, args[0], cw);
3291 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003292 break;
3293
3294 case PE_ARG_MISSING:
3295 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3296 file, linenum, args[0], cw);
3297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
3299
3300 case PE_ARG_NOT_USED:
3301 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3302 file, linenum, args[0], cw);
3303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
3305
3306 default:
3307 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3308 file, linenum, args[0], cw);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003311 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003312 }
3313 myidx++;
3314 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003315 else {
3316 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3317 file, linenum, args[myidx]);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003320 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003321 }
3322
3323 if (!curproxy->table.size) {
3324 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3325 file, linenum);
3326 err_code |= ERR_ALERT | ERR_FATAL;
3327 goto out;
3328 }
3329
3330 if (curproxy->table.type == (unsigned int)-1) {
3331 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3332 file, linenum);
3333 err_code |= ERR_ALERT | ERR_FATAL;
3334 goto out;
3335 }
3336 }
3337 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003338 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003339 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003340 int myidx = 0;
3341 const char *name = NULL;
3342 int flags;
3343
3344 if (curproxy == &defproxy) {
3345 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3346 err_code |= ERR_ALERT | ERR_FATAL;
3347 goto out;
3348 }
3349
3350 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3351 err_code |= ERR_WARN;
3352 goto out;
3353 }
3354
3355 myidx++;
3356 if ((strcmp(args[myidx], "store") == 0) ||
3357 (strcmp(args[myidx], "store-request") == 0)) {
3358 myidx++;
3359 flags = STK_IS_STORE;
3360 }
3361 else if (strcmp(args[myidx], "store-response") == 0) {
3362 myidx++;
3363 flags = STK_IS_STORE | STK_ON_RSP;
3364 }
3365 else if (strcmp(args[myidx], "match") == 0) {
3366 myidx++;
3367 flags = STK_IS_MATCH;
3368 }
3369 else if (strcmp(args[myidx], "on") == 0) {
3370 myidx++;
3371 flags = STK_IS_MATCH | STK_IS_STORE;
3372 }
3373 else {
3374 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
3377 }
3378
3379 if (*(args[myidx]) == 0) {
3380 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
3383 }
3384
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003385 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003386 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003387 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003388 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
3392
3393 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003394 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3395 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3396 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003397 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003398 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003399 goto out;
3400 }
3401 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003402 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3403 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3404 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003405 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003406 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003407 goto out;
3408 }
3409 }
3410
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003411 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003412 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003413
Emeric Brunb982a3d2010-01-04 15:45:53 +01003414 if (strcmp(args[myidx], "table") == 0) {
3415 myidx++;
3416 name = args[myidx++];
3417 }
3418
Willy Tarreauef6494c2010-01-28 17:12:36 +01003419 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003420 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3421 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3422 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003423 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003424 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003425 goto out;
3426 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003427 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003428 else if (*(args[myidx])) {
3429 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3430 file, linenum, args[0], args[myidx]);
3431 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003432 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003433 goto out;
3434 }
Emeric Brun97679e72010-09-23 17:56:44 +02003435 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003436 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003437 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003438 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003439
Emeric Brunb982a3d2010-01-04 15:45:53 +01003440 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3441 rule->cond = cond;
3442 rule->expr = expr;
3443 rule->flags = flags;
3444 rule->table.name = name ? strdup(name) : NULL;
3445 LIST_INIT(&rule->list);
3446 if (flags & STK_ON_RSP)
3447 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3448 else
3449 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3450 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 else if (!strcmp(args[0], "stats")) {
3452 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3453 curproxy->uri_auth = NULL; /* we must detach from the default config */
3454
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003455 if (!*args[1]) {
3456 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003457 } else if (!strcmp(args[1], "admin")) {
3458 struct stats_admin_rule *rule;
3459
3460 if (curproxy == &defproxy) {
3461 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3462 err_code |= ERR_ALERT | ERR_FATAL;
3463 goto out;
3464 }
3465
3466 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3467 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3468 err_code |= ERR_ALERT | ERR_ABORT;
3469 goto out;
3470 }
3471
3472 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3473 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3474 file, linenum, args[0], args[1]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003478 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3479 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3480 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
3483 }
3484
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003485 err_code |= warnif_cond_conflicts(cond,
3486 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3487 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003488
3489 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3490 rule->cond = cond;
3491 LIST_INIT(&rule->list);
3492 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 } else if (!strcmp(args[1], "uri")) {
3494 if (*(args[2]) == 0) {
3495 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003498 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3499 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003500 err_code |= ERR_ALERT | ERR_ABORT;
3501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 }
3503 } else if (!strcmp(args[1], "realm")) {
3504 if (*(args[2]) == 0) {
3505 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003508 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3509 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003510 err_code |= ERR_ALERT | ERR_ABORT;
3511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003512 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003513 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003514 unsigned interval;
3515
3516 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3517 if (err) {
3518 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3519 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_FATAL;
3521 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003522 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3523 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003524 err_code |= ERR_ALERT | ERR_ABORT;
3525 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003526 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003527 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003528 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003529
3530 if (curproxy == &defproxy) {
3531 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3532 err_code |= ERR_ALERT | ERR_FATAL;
3533 goto out;
3534 }
3535
3536 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3537 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3538 err_code |= ERR_ALERT | ERR_ABORT;
3539 goto out;
3540 }
3541
Willy Tarreauff011f22011-01-06 17:51:27 +01003542 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3543 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003544 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3545 file, linenum, args[0]);
3546 err_code |= ERR_WARN;
3547 }
3548
Willy Tarreauff011f22011-01-06 17:51:27 +01003549 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003550
Willy Tarreauff011f22011-01-06 17:51:27 +01003551 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003552 err_code |= ERR_ALERT | ERR_ABORT;
3553 goto out;
3554 }
3555
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003556 err_code |= warnif_cond_conflicts(rule->cond,
3557 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3558 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003559 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003560
Willy Tarreaubaaee002006-06-26 02:48:02 +02003561 } else if (!strcmp(args[1], "auth")) {
3562 if (*(args[2]) == 0) {
3563 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003564 err_code |= ERR_ALERT | ERR_FATAL;
3565 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3567 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003568 err_code |= ERR_ALERT | ERR_ABORT;
3569 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 }
3571 } else if (!strcmp(args[1], "scope")) {
3572 if (*(args[2]) == 0) {
3573 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003576 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3577 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003578 err_code |= ERR_ALERT | ERR_ABORT;
3579 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003580 }
3581 } else if (!strcmp(args[1], "enable")) {
3582 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3583 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003584 err_code |= ERR_ALERT | ERR_ABORT;
3585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003586 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003587 } else if (!strcmp(args[1], "hide-version")) {
3588 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3589 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003590 err_code |= ERR_ALERT | ERR_ABORT;
3591 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003592 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003593 } else if (!strcmp(args[1], "show-legends")) {
3594 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3595 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3596 err_code |= ERR_ALERT | ERR_ABORT;
3597 goto out;
3598 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003599 } else if (!strcmp(args[1], "show-node")) {
3600
3601 if (*args[2]) {
3602 int i;
3603 char c;
3604
3605 for (i=0; args[2][i]; i++) {
3606 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003607 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3608 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003609 break;
3610 }
3611
3612 if (!i || args[2][i]) {
3613 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3614 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3615 file, linenum, args[0], args[1]);
3616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
3618 }
3619 }
3620
3621 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3622 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3623 err_code |= ERR_ALERT | ERR_ABORT;
3624 goto out;
3625 }
3626 } else if (!strcmp(args[1], "show-desc")) {
3627 char *desc = NULL;
3628
3629 if (*args[2]) {
3630 int i, len=0;
3631 char *d;
3632
Willy Tarreau348acfe2014-04-14 15:00:39 +02003633 for (i = 2; *args[i]; i++)
3634 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003635
3636 desc = d = (char *)calloc(1, len);
3637
Willy Tarreau348acfe2014-04-14 15:00:39 +02003638 d += snprintf(d, desc + len - d, "%s", args[2]);
3639 for (i = 3; *args[i]; i++)
3640 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003641 }
3642
3643 if (!*args[2] && !global.desc)
3644 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3645 file, linenum, args[1]);
3646 else {
3647 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3648 free(desc);
3649 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3650 err_code |= ERR_ALERT | ERR_ABORT;
3651 goto out;
3652 }
3653 free(desc);
3654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003655 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003656stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003657 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 +01003658 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003661 }
3662 }
3663 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003664 int optnum;
3665
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003666 if (*(args[1]) == '\0') {
3667 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3668 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003669 err_code |= ERR_ALERT | ERR_FATAL;
3670 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003671 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003672
3673 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3674 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003675 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3676 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3677 file, linenum, cfg_opts[optnum].name);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
Willy Tarreau93893792009-07-23 13:19:11 +02003681 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3682 err_code |= ERR_WARN;
3683 goto out;
3684 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003685
Willy Tarreau3842f002009-06-14 11:39:52 +02003686 curproxy->no_options &= ~cfg_opts[optnum].val;
3687 curproxy->options &= ~cfg_opts[optnum].val;
3688
3689 switch (kwm) {
3690 case KWM_STD:
3691 curproxy->options |= cfg_opts[optnum].val;
3692 break;
3693 case KWM_NO:
3694 curproxy->no_options |= cfg_opts[optnum].val;
3695 break;
3696 case KWM_DEF: /* already cleared */
3697 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003698 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003699
Willy Tarreau93893792009-07-23 13:19:11 +02003700 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003701 }
3702 }
3703
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003704 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3705 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003706 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3707 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3708 file, linenum, cfg_opts2[optnum].name);
3709 err_code |= ERR_ALERT | ERR_FATAL;
3710 goto out;
3711 }
Willy Tarreau93893792009-07-23 13:19:11 +02003712 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3713 err_code |= ERR_WARN;
3714 goto out;
3715 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003716
Willy Tarreau3842f002009-06-14 11:39:52 +02003717 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3718 curproxy->options2 &= ~cfg_opts2[optnum].val;
3719
3720 switch (kwm) {
3721 case KWM_STD:
3722 curproxy->options2 |= cfg_opts2[optnum].val;
3723 break;
3724 case KWM_NO:
3725 curproxy->no_options2 |= cfg_opts2[optnum].val;
3726 break;
3727 case KWM_DEF: /* already cleared */
3728 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003729 }
Willy Tarreau93893792009-07-23 13:19:11 +02003730 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003731 }
3732 }
3733
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003734 /* HTTP options override each other. They can be cancelled using
3735 * "no option xxx" which only switches to default mode if the mode
3736 * was this one (useful for cancelling options set in defaults
3737 * sections).
3738 */
3739 if (strcmp(args[1], "httpclose") == 0) {
3740 if (kwm == KWM_STD) {
3741 curproxy->options &= ~PR_O_HTTP_MODE;
3742 curproxy->options |= PR_O_HTTP_PCL;
3743 goto out;
3744 }
3745 else if (kwm == KWM_NO) {
3746 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3747 curproxy->options &= ~PR_O_HTTP_MODE;
3748 goto out;
3749 }
3750 }
3751 else if (strcmp(args[1], "forceclose") == 0) {
3752 if (kwm == KWM_STD) {
3753 curproxy->options &= ~PR_O_HTTP_MODE;
3754 curproxy->options |= PR_O_HTTP_FCL;
3755 goto out;
3756 }
3757 else if (kwm == KWM_NO) {
3758 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3759 curproxy->options &= ~PR_O_HTTP_MODE;
3760 goto out;
3761 }
3762 }
3763 else if (strcmp(args[1], "http-server-close") == 0) {
3764 if (kwm == KWM_STD) {
3765 curproxy->options &= ~PR_O_HTTP_MODE;
3766 curproxy->options |= PR_O_HTTP_SCL;
3767 goto out;
3768 }
3769 else if (kwm == KWM_NO) {
3770 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3771 curproxy->options &= ~PR_O_HTTP_MODE;
3772 goto out;
3773 }
3774 }
3775 else if (strcmp(args[1], "http-keep-alive") == 0) {
3776 if (kwm == KWM_STD) {
3777 curproxy->options &= ~PR_O_HTTP_MODE;
3778 curproxy->options |= PR_O_HTTP_KAL;
3779 goto out;
3780 }
3781 else if (kwm == KWM_NO) {
3782 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3783 curproxy->options &= ~PR_O_HTTP_MODE;
3784 goto out;
3785 }
3786 }
3787 else if (strcmp(args[1], "http-tunnel") == 0) {
3788 if (kwm == KWM_STD) {
3789 curproxy->options &= ~PR_O_HTTP_MODE;
3790 curproxy->options |= PR_O_HTTP_TUN;
3791 goto out;
3792 }
3793 else if (kwm == KWM_NO) {
3794 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3795 curproxy->options &= ~PR_O_HTTP_MODE;
3796 goto out;
3797 }
3798 }
3799
Willy Tarreau3842f002009-06-14 11:39:52 +02003800 if (kwm != KWM_STD) {
3801 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003802 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003805 }
3806
Emeric Brun3a058f32009-06-30 18:26:00 +02003807 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003808 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003809 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003810 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003811 if (*(args[2]) != '\0') {
3812 if (!strcmp(args[2], "clf")) {
3813 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003814 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003815 } else {
William Lallemand629b1c02015-05-28 18:02:48 +02003816 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003817 err_code |= ERR_ALERT | ERR_FATAL;
3818 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003819 }
3820 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003821 if (curproxy->conf.logformat_string != default_http_log_format &&
3822 curproxy->conf.logformat_string != default_tcp_log_format &&
3823 curproxy->conf.logformat_string != clf_http_log_format)
3824 free(curproxy->conf.logformat_string);
3825 curproxy->conf.logformat_string = logformat;
3826
3827 free(curproxy->conf.lfs_file);
3828 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3829 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003830 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003831 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003833 if (curproxy->conf.logformat_string != default_http_log_format &&
3834 curproxy->conf.logformat_string != default_tcp_log_format &&
3835 curproxy->conf.logformat_string != clf_http_log_format)
3836 free(curproxy->conf.logformat_string);
3837 curproxy->conf.logformat_string = default_tcp_log_format;
3838
3839 free(curproxy->conf.lfs_file);
3840 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3841 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003842 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 else if (!strcmp(args[1], "tcpka")) {
3844 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003845 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003847
3848 if (curproxy->cap & PR_CAP_FE)
3849 curproxy->options |= PR_O_TCP_CLI_KA;
3850 if (curproxy->cap & PR_CAP_BE)
3851 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
3853 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003854 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_WARN;
3856
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003858 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003859 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003860 curproxy->options2 &= ~PR_O2_CHK_ANY;
3861 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003862 if (!*args[2]) { /* no argument */
3863 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3864 curproxy->check_len = strlen(DEF_CHECK_REQ);
3865 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003866 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003867 curproxy->check_req = (char *)malloc(reqlen);
3868 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003869 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003870 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003871 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003872 if (*args[4])
3873 reqlen += strlen(args[4]);
3874 else
3875 reqlen += strlen("HTTP/1.0");
3876
3877 curproxy->check_req = (char *)malloc(reqlen);
3878 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003879 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003880 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003881 }
3882 else if (!strcmp(args[1], "ssl-hello-chk")) {
3883 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003884 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003885 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003886
Willy Tarreaua534fea2008-08-03 12:19:50 +02003887 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003888 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003889 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003890 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003891 }
Willy Tarreau23677902007-05-08 23:50:35 +02003892 else if (!strcmp(args[1], "smtpchk")) {
3893 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003894 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003895 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003896 curproxy->options2 &= ~PR_O2_CHK_ANY;
3897 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003898
3899 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3900 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3901 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3902 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3903 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3904 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3905 curproxy->check_req = (char *)malloc(reqlen);
3906 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3907 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3908 } else {
3909 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3910 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3911 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3912 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3913 }
3914 }
3915 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003916 else if (!strcmp(args[1], "pgsql-check")) {
3917 /* use PostgreSQL request to check servers' health */
3918 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3919 err_code |= ERR_WARN;
3920
3921 free(curproxy->check_req);
3922 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003923 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003924 curproxy->options2 |= PR_O2_PGSQL_CHK;
3925
3926 if (*(args[2])) {
3927 int cur_arg = 2;
3928
3929 while (*(args[cur_arg])) {
3930 if (strcmp(args[cur_arg], "user") == 0) {
3931 char * packet;
3932 uint32_t packet_len;
3933 uint32_t pv;
3934
3935 /* suboption header - needs additional argument for it */
3936 if (*(args[cur_arg+1]) == 0) {
3937 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3938 file, linenum, args[0], args[1], args[cur_arg]);
3939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
3941 }
3942
3943 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3944 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3945 pv = htonl(0x30000); /* protocol version 3.0 */
3946
3947 packet = (char*) calloc(1, packet_len);
3948
3949 memcpy(packet + 4, &pv, 4);
3950
3951 /* copy "user" */
3952 memcpy(packet + 8, "user", 4);
3953
3954 /* copy username */
3955 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3956
3957 free(curproxy->check_req);
3958 curproxy->check_req = packet;
3959 curproxy->check_len = packet_len;
3960
3961 packet_len = htonl(packet_len);
3962 memcpy(packet, &packet_len, 4);
3963 cur_arg += 2;
3964 } else {
3965 /* unknown suboption - catchall */
3966 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3967 file, linenum, args[0], args[1]);
3968 err_code |= ERR_ALERT | ERR_FATAL;
3969 goto out;
3970 }
3971 } /* end while loop */
3972 }
3973 }
3974
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003975 else if (!strcmp(args[1], "redis-check")) {
3976 /* use REDIS PING request to check servers' health */
3977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3978 err_code |= ERR_WARN;
3979
3980 free(curproxy->check_req);
3981 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003982 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003983 curproxy->options2 |= PR_O2_REDIS_CHK;
3984
3985 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3986 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3987 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3988 }
3989
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003990 else if (!strcmp(args[1], "mysql-check")) {
3991 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003992 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3993 err_code |= ERR_WARN;
3994
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003995 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003996 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003997 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003998 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003999
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004000 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004001 * const char mysql40_client_auth_pkt[] = {
4002 * "\x0e\x00\x00" // packet length
4003 * "\x01" // packet number
4004 * "\x00\x00" // client capabilities
4005 * "\x00\x00\x01" // max packet
4006 * "haproxy\x00" // username (null terminated string)
4007 * "\x00" // filler (always 0x00)
4008 * "\x01\x00\x00" // packet length
4009 * "\x00" // packet number
4010 * "\x01" // COM_QUIT command
4011 * };
4012 */
4013
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004014 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4015 * const char mysql41_client_auth_pkt[] = {
4016 * "\x0e\x00\x00\" // packet length
4017 * "\x01" // packet number
4018 * "\x00\x00\x00\x00" // client capabilities
4019 * "\x00\x00\x00\x01" // max packet
4020 * "\x21" // character set (UTF-8)
4021 * char[23] // All zeroes
4022 * "haproxy\x00" // username (null terminated string)
4023 * "\x00" // filler (always 0x00)
4024 * "\x01\x00\x00" // packet length
4025 * "\x00" // packet number
4026 * "\x01" // COM_QUIT command
4027 * };
4028 */
4029
4030
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004031 if (*(args[2])) {
4032 int cur_arg = 2;
4033
4034 while (*(args[cur_arg])) {
4035 if (strcmp(args[cur_arg], "user") == 0) {
4036 char *mysqluser;
4037 int packetlen, reqlen, userlen;
4038
4039 /* suboption header - needs additional argument for it */
4040 if (*(args[cur_arg+1]) == 0) {
4041 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4042 file, linenum, args[0], args[1], args[cur_arg]);
4043 err_code |= ERR_ALERT | ERR_FATAL;
4044 goto out;
4045 }
4046 mysqluser = args[cur_arg + 1];
4047 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004048
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004049 if (*(args[cur_arg+2])) {
4050 if (!strcmp(args[cur_arg+2], "post-41")) {
4051 packetlen = userlen + 7 + 27;
4052 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004053
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004054 free(curproxy->check_req);
4055 curproxy->check_req = (char *)calloc(1, reqlen);
4056 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004057
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004058 snprintf(curproxy->check_req, 4, "%c%c%c",
4059 ((unsigned char) packetlen & 0xff),
4060 ((unsigned char) (packetlen >> 8) & 0xff),
4061 ((unsigned char) (packetlen >> 16) & 0xff));
4062
4063 curproxy->check_req[3] = 1;
4064 curproxy->check_req[5] = 130;
4065 curproxy->check_req[11] = 1;
4066 curproxy->check_req[12] = 33;
4067 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4068 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4069 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4070 cur_arg += 3;
4071 } else {
4072 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 } else {
4077 packetlen = userlen + 7;
4078 reqlen = packetlen + 9;
4079
4080 free(curproxy->check_req);
4081 curproxy->check_req = (char *)calloc(1, reqlen);
4082 curproxy->check_len = reqlen;
4083
4084 snprintf(curproxy->check_req, 4, "%c%c%c",
4085 ((unsigned char) packetlen & 0xff),
4086 ((unsigned char) (packetlen >> 8) & 0xff),
4087 ((unsigned char) (packetlen >> 16) & 0xff));
4088
4089 curproxy->check_req[3] = 1;
4090 curproxy->check_req[5] = 128;
4091 curproxy->check_req[8] = 1;
4092 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4093 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4094 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4095 cur_arg += 2;
4096 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004097 } else {
4098 /* unknown suboption - catchall */
4099 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4100 file, linenum, args[0], args[1]);
4101 err_code |= ERR_ALERT | ERR_FATAL;
4102 goto out;
4103 }
4104 } /* end while loop */
4105 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004106 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004107 else if (!strcmp(args[1], "ldap-check")) {
4108 /* use LDAP request to check servers' health */
4109 free(curproxy->check_req);
4110 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004111 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004112 curproxy->options2 |= PR_O2_LDAP_CHK;
4113
4114 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4115 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4116 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4117 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004118 else if (!strcmp(args[1], "tcp-check")) {
4119 /* use raw TCPCHK send/expect to check servers' health */
4120 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4121 err_code |= ERR_WARN;
4122
4123 free(curproxy->check_req);
4124 curproxy->check_req = NULL;
4125 curproxy->options2 &= ~PR_O2_CHK_ANY;
4126 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4127 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004128 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004129 int cur_arg;
4130
4131 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4132 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004133 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004134
Willy Tarreau87cf5142011-08-19 22:57:24 +02004135 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004136
4137 free(curproxy->fwdfor_hdr_name);
4138 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4139 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4140
4141 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4142 cur_arg = 2;
4143 while (*(args[cur_arg])) {
4144 if (!strcmp(args[cur_arg], "except")) {
4145 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004146 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004147 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4148 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004151 }
4152 /* flush useless bits */
4153 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004154 cur_arg += 2;
4155 } else if (!strcmp(args[cur_arg], "header")) {
4156 /* suboption header - needs additional argument for it */
4157 if (*(args[cur_arg+1]) == 0) {
4158 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4159 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004162 }
4163 free(curproxy->fwdfor_hdr_name);
4164 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4165 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4166 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004167 } else if (!strcmp(args[cur_arg], "if-none")) {
4168 curproxy->options &= ~PR_O_FF_ALWAYS;
4169 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004170 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004171 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004172 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004173 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004174 err_code |= ERR_ALERT | ERR_FATAL;
4175 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004176 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004177 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004178 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004179 else if (!strcmp(args[1], "originalto")) {
4180 int cur_arg;
4181
4182 /* insert x-original-to field, but not for the IP address listed as an except.
4183 * set default options (ie: bitfield, header name, etc)
4184 */
4185
4186 curproxy->options |= PR_O_ORGTO;
4187
4188 free(curproxy->orgto_hdr_name);
4189 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4190 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4191
Willy Tarreau87cf5142011-08-19 22:57:24 +02004192 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004193 cur_arg = 2;
4194 while (*(args[cur_arg])) {
4195 if (!strcmp(args[cur_arg], "except")) {
4196 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004197 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 +02004198 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4199 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004202 }
4203 /* flush useless bits */
4204 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4205 cur_arg += 2;
4206 } else if (!strcmp(args[cur_arg], "header")) {
4207 /* suboption header - needs additional argument for it */
4208 if (*(args[cur_arg+1]) == 0) {
4209 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4210 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004211 err_code |= ERR_ALERT | ERR_FATAL;
4212 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004213 }
4214 free(curproxy->orgto_hdr_name);
4215 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4216 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4217 cur_arg += 2;
4218 } else {
4219 /* unknown suboption - catchall */
4220 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4221 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004222 err_code |= ERR_ALERT | ERR_FATAL;
4223 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004224 }
4225 } /* end while loop */
4226 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004227 else {
4228 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004229 err_code |= ERR_ALERT | ERR_FATAL;
4230 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004231 }
Willy Tarreau93893792009-07-23 13:19:11 +02004232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004233 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004234 else if (!strcmp(args[0], "default_backend")) {
4235 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004236 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004237
4238 if (*(args[1]) == 0) {
4239 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004240 err_code |= ERR_ALERT | ERR_FATAL;
4241 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004242 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004243 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004244 curproxy->defbe.name = strdup(args[1]);
4245 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004247 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004248 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004249
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004250 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4251 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 +01004252 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004254 /* enable reconnections to dispatch */
4255 curproxy->options |= PR_O_REDISP;
4256 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004257 else if (!strcmp(args[0], "http-check")) {
4258 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004260
4261 if (strcmp(args[1], "disable-on-404") == 0) {
4262 /* enable a graceful server shutdown on an HTTP 404 response */
4263 curproxy->options |= PR_O_DISABLE404;
4264 }
Willy Tarreauef781042010-01-27 11:53:01 +01004265 else if (strcmp(args[1], "send-state") == 0) {
4266 /* enable emission of the apparent state of a server in HTTP checks */
4267 curproxy->options2 |= PR_O2_CHK_SNDST;
4268 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004269 else if (strcmp(args[1], "expect") == 0) {
4270 const char *ptr_arg;
4271 int cur_arg;
4272
4273 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4274 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4275 err_code |= ERR_ALERT | ERR_FATAL;
4276 goto out;
4277 }
4278
4279 cur_arg = 2;
4280 /* consider exclamation marks, sole or at the beginning of a word */
4281 while (*(ptr_arg = args[cur_arg])) {
4282 while (*ptr_arg == '!') {
4283 curproxy->options2 ^= PR_O2_EXP_INV;
4284 ptr_arg++;
4285 }
4286 if (*ptr_arg)
4287 break;
4288 cur_arg++;
4289 }
4290 /* now ptr_arg points to the beginning of a word past any possible
4291 * exclamation mark, and cur_arg is the argument which holds this word.
4292 */
4293 if (strcmp(ptr_arg, "status") == 0) {
4294 if (!*(args[cur_arg + 1])) {
4295 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4296 file, linenum, args[0], args[1], ptr_arg);
4297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
4300 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004301 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004302 curproxy->expect_str = strdup(args[cur_arg + 1]);
4303 }
4304 else if (strcmp(ptr_arg, "string") == 0) {
4305 if (!*(args[cur_arg + 1])) {
4306 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4307 file, linenum, args[0], args[1], ptr_arg);
4308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004312 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004313 curproxy->expect_str = strdup(args[cur_arg + 1]);
4314 }
4315 else if (strcmp(ptr_arg, "rstatus") == 0) {
4316 if (!*(args[cur_arg + 1])) {
4317 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4318 file, linenum, args[0], args[1], ptr_arg);
4319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
4321 }
4322 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004323 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004324 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004325 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004326 free(curproxy->expect_regex);
4327 curproxy->expect_regex = NULL;
4328 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004329 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004330 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4331 error = NULL;
4332 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4333 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4334 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4335 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004336 err_code |= ERR_ALERT | ERR_FATAL;
4337 goto out;
4338 }
4339 }
4340 else if (strcmp(ptr_arg, "rstring") == 0) {
4341 if (!*(args[cur_arg + 1])) {
4342 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4343 file, linenum, args[0], args[1], ptr_arg);
4344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
4346 }
4347 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004348 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004349 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004350 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004351 free(curproxy->expect_regex);
4352 curproxy->expect_regex = NULL;
4353 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004354 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004355 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4356 error = NULL;
4357 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4358 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4359 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4360 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004361 err_code |= ERR_ALERT | ERR_FATAL;
4362 goto out;
4363 }
4364 }
4365 else {
4366 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4367 file, linenum, args[0], args[1], ptr_arg);
4368 err_code |= ERR_ALERT | ERR_FATAL;
4369 goto out;
4370 }
4371 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004372 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004373 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 +02004374 err_code |= ERR_ALERT | ERR_FATAL;
4375 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004376 }
4377 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004378 else if (!strcmp(args[0], "tcp-check")) {
4379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4380 err_code |= ERR_WARN;
4381
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004382 if (strcmp(args[1], "connect") == 0) {
4383 const char *ptr_arg;
4384 int cur_arg;
4385 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004386
4387 /* check if first rule is also a 'connect' action */
Willy Tarreau5bff0592015-05-13 12:24:53 +02004388 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
Willy Tarreau97fccc82015-05-13 12:08:21 +02004389
Willy Tarreau5bff0592015-05-13 12:24:53 +02004390 if (&tcpcheck->list != &curproxy->tcpcheck_rules
4391 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4392 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4393 file, linenum);
4394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004396 }
4397
4398 cur_arg = 2;
4399 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4400 tcpcheck->action = TCPCHK_ACT_CONNECT;
4401
4402 /* parsing each parameters to fill up the rule */
4403 while (*(ptr_arg = args[cur_arg])) {
4404 /* tcp port */
4405 if (strcmp(args[cur_arg], "port") == 0) {
4406 if ( (atol(args[cur_arg + 1]) > 65535) ||
4407 (atol(args[cur_arg + 1]) < 1) ){
4408 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4409 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4410 err_code |= ERR_ALERT | ERR_FATAL;
4411 goto out;
4412 }
4413 tcpcheck->port = atol(args[cur_arg + 1]);
4414 cur_arg += 2;
4415 }
4416 /* send proxy protocol */
4417 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4418 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4419 cur_arg++;
4420 }
4421#ifdef USE_OPENSSL
4422 else if (strcmp(args[cur_arg], "ssl") == 0) {
4423 curproxy->options |= PR_O_TCPCHK_SSL;
4424 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4425 cur_arg++;
4426 }
4427#endif /* USE_OPENSSL */
4428 else {
4429#ifdef USE_OPENSSL
4430 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4431#else /* USE_OPENSSL */
4432 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4433#endif /* USE_OPENSSL */
4434 file, linenum, args[0], args[1], args[cur_arg]);
4435 err_code |= ERR_ALERT | ERR_FATAL;
4436 goto out;
4437 }
4438
4439 }
4440
4441 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4442 }
4443 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004444 if (! *(args[2]) ) {
4445 /* SEND string expected */
4446 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4447 file, linenum, args[0], args[1], args[2]);
4448 err_code |= ERR_ALERT | ERR_FATAL;
4449 goto out;
4450 } else {
4451 struct tcpcheck_rule *tcpcheck;
4452
4453 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4454
4455 tcpcheck->action = TCPCHK_ACT_SEND;
4456 tcpcheck->string_len = strlen(args[2]);
4457 tcpcheck->string = strdup(args[2]);
4458 tcpcheck->expect_regex = NULL;
4459
4460 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4461 }
4462 }
4463 else if (strcmp(args[1], "send-binary") == 0) {
4464 if (! *(args[2]) ) {
4465 /* SEND binary string expected */
4466 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4467 file, linenum, args[0], args[1], args[2]);
4468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
4470 } else {
4471 struct tcpcheck_rule *tcpcheck;
4472 char *err = NULL;
4473
4474 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4475
4476 tcpcheck->action = TCPCHK_ACT_SEND;
4477 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4478 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4479 file, linenum, args[0], args[1], args[2], err);
4480 err_code |= ERR_ALERT | ERR_FATAL;
4481 goto out;
4482 }
4483 tcpcheck->expect_regex = NULL;
4484
4485 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4486 }
4487 }
4488 else if (strcmp(args[1], "expect") == 0) {
4489 const char *ptr_arg;
4490 int cur_arg;
4491 int inverse = 0;
4492
4493 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4494 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4495 err_code |= ERR_ALERT | ERR_FATAL;
4496 goto out;
4497 }
4498
4499 cur_arg = 2;
4500 /* consider exclamation marks, sole or at the beginning of a word */
4501 while (*(ptr_arg = args[cur_arg])) {
4502 while (*ptr_arg == '!') {
4503 inverse = !inverse;
4504 ptr_arg++;
4505 }
4506 if (*ptr_arg)
4507 break;
4508 cur_arg++;
4509 }
4510 /* now ptr_arg points to the beginning of a word past any possible
4511 * exclamation mark, and cur_arg is the argument which holds this word.
4512 */
4513 if (strcmp(ptr_arg, "binary") == 0) {
4514 if (!*(args[cur_arg + 1])) {
4515 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4516 file, linenum, args[0], args[1], ptr_arg);
4517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
4519 }
4520 struct tcpcheck_rule *tcpcheck;
4521 char *err = NULL;
4522
4523 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4524
4525 tcpcheck->action = TCPCHK_ACT_EXPECT;
4526 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4527 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4528 file, linenum, args[0], args[1], args[2], err);
4529 err_code |= ERR_ALERT | ERR_FATAL;
4530 goto out;
4531 }
4532 tcpcheck->expect_regex = NULL;
4533 tcpcheck->inverse = inverse;
4534
4535 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4536 }
4537 else if (strcmp(ptr_arg, "string") == 0) {
4538 if (!*(args[cur_arg + 1])) {
4539 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4540 file, linenum, args[0], args[1], ptr_arg);
4541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
4543 }
4544 struct tcpcheck_rule *tcpcheck;
4545
4546 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4547
4548 tcpcheck->action = TCPCHK_ACT_EXPECT;
4549 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4550 tcpcheck->string = strdup(args[cur_arg + 1]);
4551 tcpcheck->expect_regex = NULL;
4552 tcpcheck->inverse = inverse;
4553
4554 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4555 }
4556 else if (strcmp(ptr_arg, "rstring") == 0) {
4557 if (!*(args[cur_arg + 1])) {
4558 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4559 file, linenum, args[0], args[1], ptr_arg);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
4563 struct tcpcheck_rule *tcpcheck;
4564
4565 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4566
4567 tcpcheck->action = TCPCHK_ACT_EXPECT;
4568 tcpcheck->string_len = 0;
4569 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004570 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4571 error = NULL;
4572 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4573 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4574 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4575 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
4578 }
4579 tcpcheck->inverse = inverse;
4580
4581 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4582 }
4583 else {
4584 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4585 file, linenum, args[0], args[1], ptr_arg);
4586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
4588 }
4589 }
4590 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004591 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
4594 }
4595 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004596 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004597 if (curproxy == &defproxy) {
4598 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004601 }
4602
Willy Tarreaub80c2302007-11-30 20:51:32 +01004603 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004604 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004605
4606 if (strcmp(args[1], "fail") == 0) {
4607 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004608 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004609 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4610 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_ALERT | ERR_FATAL;
4612 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004613 }
4614
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004615 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4616 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4617 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004618 err_code |= ERR_ALERT | ERR_FATAL;
4619 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004620 }
4621 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4622 }
4623 else {
4624 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004625 err_code |= ERR_ALERT | ERR_FATAL;
4626 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004627 }
4628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004629#ifdef TPROXY
4630 else if (!strcmp(args[0], "transparent")) {
4631 /* enable transparent proxy connections */
4632 curproxy->options |= PR_O_TRANSP;
4633 }
4634#endif
4635 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004638
Willy Tarreaubaaee002006-06-26 02:48:02 +02004639 if (*(args[1]) == 0) {
4640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004641 err_code |= ERR_ALERT | ERR_FATAL;
4642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 }
4644 curproxy->maxconn = atol(args[1]);
4645 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004646 else if (!strcmp(args[0], "backlog")) { /* backlog */
4647 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004648 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004649
4650 if (*(args[1]) == 0) {
4651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004654 }
4655 curproxy->backlog = atol(args[1]);
4656 }
Willy Tarreau86034312006-12-29 00:10:33 +01004657 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004658 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004659 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004660
Willy Tarreau86034312006-12-29 00:10:33 +01004661 if (*(args[1]) == 0) {
4662 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004663 err_code |= ERR_ALERT | ERR_FATAL;
4664 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004665 }
4666 curproxy->fullconn = atol(args[1]);
4667 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004668 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4669 if (*(args[1]) == 0) {
4670 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004671 err_code |= ERR_ALERT | ERR_FATAL;
4672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004673 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004674 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4675 if (err) {
4676 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4677 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004678 err_code |= ERR_ALERT | ERR_FATAL;
4679 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004680 }
4681 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004682 }
4683 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004684 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004685 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004686 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004687
Willy Tarreaubaaee002006-06-26 02:48:02 +02004688 if (curproxy == &defproxy) {
4689 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004692 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004693 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004694 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004695
Willy Tarreau902636f2013-03-10 19:44:48 +01004696 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004697 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004698 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004699 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004700 goto out;
4701 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004702
4703 proto = protocol_by_family(sk->ss_family);
4704 if (!proto || !proto->connect) {
4705 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4706 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004707 err_code |= ERR_ALERT | ERR_FATAL;
4708 goto out;
4709 }
4710
4711 if (port1 != port2) {
4712 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4713 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004716 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004717
4718 if (!port1) {
4719 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4720 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004721 err_code |= ERR_ALERT | ERR_FATAL;
4722 goto out;
4723 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004724
Willy Tarreaud5191e72010-02-09 20:50:45 +01004725 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004726 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004727 }
4728 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004729 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004730 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004731
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004732 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4733 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004734 err_code |= ERR_ALERT | ERR_FATAL;
4735 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004736 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004737 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004738 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004739 /**
4740 * The syntax for hash-type config element is
4741 * hash-type {map-based|consistent} [[<algo>] avalanche]
4742 *
4743 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4744 */
4745 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004746
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004747 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4748 err_code |= ERR_WARN;
4749
4750 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004751 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4752 }
4753 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004754 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4755 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004756 else if (strcmp(args[1], "avalanche") == 0) {
4757 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]);
4758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004760 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004761 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004762 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004763 err_code |= ERR_ALERT | ERR_FATAL;
4764 goto out;
4765 }
Bhaskar98634f02013-10-29 23:30:51 -04004766
4767 /* set the hash function to use */
4768 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004769 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004770 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004771
4772 /* if consistent with no argument, then avalanche modifier is also applied */
4773 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4774 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004775 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004776 /* set the hash function */
4777 if (!strcmp(args[2], "sdbm")) {
4778 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4779 }
4780 else if (!strcmp(args[2], "djb2")) {
4781 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004782 } else if (!strcmp(args[2], "wt6")) {
4783 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004784 }
4785 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004786 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 -05004787 err_code |= ERR_ALERT | ERR_FATAL;
4788 goto out;
4789 }
4790
4791 /* set the hash modifier */
4792 if (!strcmp(args[3], "avalanche")) {
4793 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4794 }
4795 else if (*args[3]) {
4796 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
4799 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004800 }
William Lallemanda73203e2012-03-12 12:48:57 +01004801 }
William Lallemanda73203e2012-03-12 12:48:57 +01004802 else if (strcmp(args[0], "unique-id-format") == 0) {
4803 if (!*(args[1])) {
4804 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4805 err_code |= ERR_ALERT | ERR_FATAL;
4806 goto out;
4807 }
William Lallemand3203ff42012-11-11 17:30:56 +01004808 if (*(args[2])) {
4809 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
4812 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004813 free(curproxy->conf.uniqueid_format_string);
4814 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004815
Willy Tarreau62a61232013-04-12 18:13:46 +02004816 free(curproxy->conf.uif_file);
4817 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4818 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004819 }
William Lallemanda73203e2012-03-12 12:48:57 +01004820
4821 else if (strcmp(args[0], "unique-id-header") == 0) {
4822 if (!*(args[1])) {
4823 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
4827 free(curproxy->header_unique_id);
4828 curproxy->header_unique_id = strdup(args[1]);
4829 }
4830
William Lallemand723b73a2012-02-08 16:37:49 +01004831 else if (strcmp(args[0], "log-format") == 0) {
4832 if (!*(args[1])) {
4833 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4834 err_code |= ERR_ALERT | ERR_FATAL;
4835 goto out;
4836 }
William Lallemand3203ff42012-11-11 17:30:56 +01004837 if (*(args[2])) {
4838 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4839 err_code |= ERR_ALERT | ERR_FATAL;
4840 goto out;
4841 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004842
Willy Tarreau62a61232013-04-12 18:13:46 +02004843 if (curproxy->conf.logformat_string != default_http_log_format &&
4844 curproxy->conf.logformat_string != default_tcp_log_format &&
4845 curproxy->conf.logformat_string != clf_http_log_format)
4846 free(curproxy->conf.logformat_string);
4847 curproxy->conf.logformat_string = strdup(args[1]);
4848
4849 free(curproxy->conf.lfs_file);
4850 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4851 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004852
4853 /* get a chance to improve log-format error reporting by
4854 * reporting the correct line-number when possible.
4855 */
4856 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4857 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4858 file, linenum, curproxy->id);
4859 err_code |= ERR_WARN;
4860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004861 }
William Lallemand723b73a2012-02-08 16:37:49 +01004862
William Lallemand0f99e342011-10-12 17:50:54 +02004863 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4864 /* delete previous herited or defined syslog servers */
4865 struct logsrv *back;
4866
4867 if (*(args[1]) != 0) {
4868 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871 }
4872
William Lallemand723b73a2012-02-08 16:37:49 +01004873 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4874 LIST_DEL(&tmplogsrv->list);
4875 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004876 }
4877 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004878 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004879 struct logsrv *logsrv;
4880
Willy Tarreaubaaee002006-06-26 02:48:02 +02004881 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004882 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004883 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004884 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004885 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004886 LIST_INIT(&node->list);
4887 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004889 }
4890 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004891 struct sockaddr_storage *sk;
4892 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004893 int arg = 0;
4894 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004895
4896 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004897
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004898 /* just after the address, a length may be specified */
4899 if (strcmp(args[arg+2], "len") == 0) {
4900 len = atoi(args[arg+3]);
4901 if (len < 80 || len > 65535) {
4902 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4903 file, linenum, args[arg+3]);
4904 err_code |= ERR_ALERT | ERR_FATAL;
4905 goto out;
4906 }
4907 logsrv->maxlen = len;
4908
4909 /* skip these two args */
4910 arg += 2;
4911 }
4912 else
4913 logsrv->maxlen = MAX_SYSLOG_LEN;
4914
4915 if (logsrv->maxlen > global.max_syslog_len) {
4916 global.max_syslog_len = logsrv->maxlen;
4917 logline = realloc(logline, global.max_syslog_len + 1);
4918 }
4919
4920 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004921 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004922 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
4925
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 }
4927
William Lallemand0f99e342011-10-12 17:50:54 +02004928 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004929 if (*(args[arg+3])) {
4930 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004931 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004932 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004933 err_code |= ERR_ALERT | ERR_FATAL;
4934 goto out;
4935
Willy Tarreaubaaee002006-06-26 02:48:02 +02004936 }
4937 }
4938
William Lallemand0f99e342011-10-12 17:50:54 +02004939 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004940 if (*(args[arg+4])) {
4941 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004942 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004943 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004944 err_code |= ERR_ALERT | ERR_FATAL;
4945 goto out;
4946
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004947 }
4948 }
4949
Willy Tarreau902636f2013-03-10 19:44:48 +01004950 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004951 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004952 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004953 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004954 goto out;
4955 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004956
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004957 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004958
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004959 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004960 if (port1 != port2) {
4961 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4962 file, linenum, args[0], args[1]);
4963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
4965 }
4966
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004967 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004968 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
William Lallemand0f99e342011-10-12 17:50:54 +02004970
4971 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else {
4974 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4975 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004976 err_code |= ERR_ALERT | ERR_FATAL;
4977 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 }
4979 }
4980 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004981 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004982 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004983 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004984 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004985
Willy Tarreau977b8e42006-12-29 14:19:17 +01004986 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004987 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004988
Willy Tarreaubaaee002006-06-26 02:48:02 +02004989 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004990 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4991 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004992 err_code |= ERR_ALERT | ERR_FATAL;
4993 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004994 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004995
4996 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004997 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4998 free(curproxy->conn_src.iface_name);
4999 curproxy->conn_src.iface_name = NULL;
5000 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005001
Willy Tarreau902636f2013-03-10 19:44:48 +01005002 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005003 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005004 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005005 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005006 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005007 goto out;
5008 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005009
5010 proto = protocol_by_family(sk->ss_family);
5011 if (!proto || !proto->connect) {
5012 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005013 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005014 err_code |= ERR_ALERT | ERR_FATAL;
5015 goto out;
5016 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005017
5018 if (port1 != port2) {
5019 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5020 file, linenum, args[0], args[1]);
5021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
5023 }
5024
Willy Tarreauef9a3602012-12-08 22:29:20 +01005025 curproxy->conn_src.source_addr = *sk;
5026 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005027
5028 cur_arg = 2;
5029 while (*(args[cur_arg])) {
5030 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005031#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5032#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005033 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005034 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5035 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005036 err_code |= ERR_ALERT | ERR_FATAL;
5037 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005038 }
5039#endif
5040 if (!*args[cur_arg + 1]) {
5041 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5042 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005045 }
5046
5047 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005048 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5049 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005050 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005051 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5052 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005053 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5054 char *name, *end;
5055
5056 name = args[cur_arg+1] + 7;
5057 while (isspace(*name))
5058 name++;
5059
5060 end = name;
5061 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5062 end++;
5063
Willy Tarreauef9a3602012-12-08 22:29:20 +01005064 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5065 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5066 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5067 curproxy->conn_src.bind_hdr_len = end - name;
5068 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5069 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5070 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005071
5072 /* now look for an occurrence number */
5073 while (isspace(*end))
5074 end++;
5075 if (*end == ',') {
5076 end++;
5077 name = end;
5078 if (*end == '-')
5079 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005080 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005081 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005082 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005083 }
5084
Willy Tarreauef9a3602012-12-08 22:29:20 +01005085 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005086 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5087 " occurrences values smaller than %d.\n",
5088 file, linenum, MAX_HDR_HISTORY);
5089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
5091 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005092 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005093 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005094
Willy Tarreau902636f2013-03-10 19:44:48 +01005095 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005096 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005097 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005098 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005099 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005100 goto out;
5101 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005102
5103 proto = protocol_by_family(sk->ss_family);
5104 if (!proto || !proto->connect) {
5105 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5106 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005107 err_code |= ERR_ALERT | ERR_FATAL;
5108 goto out;
5109 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005110
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005111 if (port1 != port2) {
5112 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5113 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005117 curproxy->conn_src.tproxy_addr = *sk;
5118 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005119 }
5120 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005121#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005122 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005123#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005124#else /* no TPROXY support */
5125 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005126 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005129#endif
5130 cur_arg += 2;
5131 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005132 }
5133
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005134 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5135#ifdef SO_BINDTODEVICE
5136 if (!*args[cur_arg + 1]) {
5137 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5138 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005139 err_code |= ERR_ALERT | ERR_FATAL;
5140 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005141 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005142 free(curproxy->conn_src.iface_name);
5143 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5144 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005145 global.last_checks |= LSTCHK_NETADM;
5146#else
5147 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5148 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005149 err_code |= ERR_ALERT | ERR_FATAL;
5150 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005151#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005152 cur_arg += 2;
5153 continue;
5154 }
5155 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005156 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005160 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005161 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5162 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5163 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005166 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005167 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005168 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005169 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5170 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005174
5175 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005176 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005177 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005178 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 }
5181 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005182 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005183 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005184 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005185 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005187 }
5188 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005189 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005190 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005191 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005192 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 }
5195 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005196 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005197 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005198 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005199 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005201 }
5202 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005203 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005204 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005205 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005206 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005208 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005209 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005210 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005211 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005212 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005213 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005214 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005215 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005216 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005218 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005219 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005220 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005221 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005222
5223 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5224 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 +01005225 }
5226 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005227 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005228 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005229 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005230 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005231 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005232
5233 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5234 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 +01005235 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005236 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005237 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5239 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005240 err_code |= ERR_ALERT | ERR_FATAL;
5241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005242 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005243
5244 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005245 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005246 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005247 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005248 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005249 }
5250 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005251 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005252 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005253 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005254 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005256 }
5257 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005258 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005259 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005260 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005261 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005262 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
5264 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005265 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005266 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005267 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005268 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005269 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 }
5271 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005272 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005273 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005274 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005275 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005278 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005279 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005280 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005281 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005282 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005283 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005285 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005286 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005287
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 if (curproxy == &defproxy) {
5289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005292 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005293 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005295
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 if (*(args[1]) == 0) {
5297 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005300 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005301
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005302 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005303 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5304 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5305 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005306 err_code |= ERR_ALERT | ERR_FATAL;
5307 goto out;
5308 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005309 err_code |= warnif_cond_conflicts(cond,
5310 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5311 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005312 }
5313 else if (*args[2]) {
5314 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5315 file, linenum, args[0], args[2]);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
5319
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005320 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005321 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005322 wl->s = strdup(args[1]);
5323 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005324 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005325 }
5326 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005327 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005328 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5329 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005332 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005333
Willy Tarreauade5ec42010-01-28 19:33:49 +01005334 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005335 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005336 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005337 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005338 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005339 }
5340 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005341 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005342 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005343 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005344 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005346 }
5347 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005348 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005349 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005350 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005351 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005353 }
5354 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005355 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5357 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005360 }
5361
Willy Tarreauade5ec42010-01-28 19:33:49 +01005362 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005363 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005364 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005365 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 }
5368 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005369 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005370 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005371 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005372 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005374 }
5375 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005376 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005377 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005378 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005379 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005381 }
5382 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005383 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005384
Willy Tarreaubaaee002006-06-26 02:48:02 +02005385 if (curproxy == &defproxy) {
5386 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005389 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005390 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005391 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005392
Willy Tarreaubaaee002006-06-26 02:48:02 +02005393 if (*(args[1]) == 0) {
5394 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005395 err_code |= ERR_ALERT | ERR_FATAL;
5396 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005397 }
5398
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005399 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005400 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5401 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5402 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005403 err_code |= ERR_ALERT | ERR_FATAL;
5404 goto out;
5405 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005406 err_code |= warnif_cond_conflicts(cond,
5407 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5408 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005409 }
5410 else if (*args[2]) {
5411 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5412 file, linenum, args[0], args[2]);
5413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
5415 }
5416
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005417 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005418 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005419 wl->s = strdup(args[1]);
5420 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005421 }
5422 else if (!strcmp(args[0], "errorloc") ||
5423 !strcmp(args[0], "errorloc302") ||
5424 !strcmp(args[0], "errorloc303")) { /* error location */
5425 int errnum, errlen;
5426 char *err;
5427
Willy Tarreau977b8e42006-12-29 14:19:17 +01005428 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005429 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005430
Willy Tarreaubaaee002006-06-26 02:48:02 +02005431 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005432 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005435 }
5436
5437 errnum = atol(args[1]);
5438 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005439 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5440 err = malloc(errlen);
5441 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005442 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005443 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5444 err = malloc(errlen);
5445 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005446 }
5447
Willy Tarreau0f772532006-12-23 20:51:41 +01005448 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5449 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005450 chunk_destroy(&curproxy->errmsg[rc]);
5451 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005452 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005455
5456 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005457 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
5458 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459 free(err);
5460 }
5461 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005462 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5463 int errnum, errlen, fd;
5464 char *err;
5465 struct stat stat;
5466
5467 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005468 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005469
5470 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005471 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005474 }
5475
5476 fd = open(args[2], O_RDONLY);
5477 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5478 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5479 file, linenum, args[2], args[1]);
5480 if (fd >= 0)
5481 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005482 err_code |= ERR_ALERT | ERR_FATAL;
5483 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005484 }
5485
Willy Tarreau27a674e2009-08-17 07:23:33 +02005486 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005487 errlen = stat.st_size;
5488 } else {
5489 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005490 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005491 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005492 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005493 }
5494
5495 err = malloc(errlen); /* malloc() must succeed during parsing */
5496 errnum = read(fd, err, errlen);
5497 if (errnum != errlen) {
5498 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5499 file, linenum, args[2], args[1]);
5500 close(fd);
5501 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005504 }
5505 close(fd);
5506
5507 errnum = atol(args[1]);
5508 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5509 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005510 chunk_destroy(&curproxy->errmsg[rc]);
5511 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005512 break;
5513 }
5514 }
5515
5516 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreau09a4a0a2015-09-27 15:13:30 +02005517 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
5518 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005519 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005520 free(err);
5521 }
5522 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005523 else if (!strcmp(args[0], "compression")) {
5524 struct comp *comp;
5525 if (curproxy->comp == NULL) {
5526 comp = calloc(1, sizeof(struct comp));
5527 curproxy->comp = comp;
5528 } else {
5529 comp = curproxy->comp;
5530 }
5531
5532 if (!strcmp(args[1], "algo")) {
5533 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005534 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005535
William Lallemand82fe75c2012-10-23 10:25:10 +02005536 cur_arg = 2;
5537 if (!*args[cur_arg]) {
5538 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5539 file, linenum, args[0]);
5540 err_code |= ERR_ALERT | ERR_FATAL;
5541 goto out;
5542 }
5543 while (*(args[cur_arg])) {
5544 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5545 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5546 file, linenum, args[0], args[cur_arg]);
5547 err_code |= ERR_ALERT | ERR_FATAL;
5548 goto out;
5549 }
William Lallemand552df672012-11-07 13:21:47 +01005550 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5551 curproxy->comp->algos->end(&ctx);
5552 } else {
5553 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5554 file, linenum, args[0], args[cur_arg]);
5555 err_code |= ERR_ALERT | ERR_FATAL;
5556 goto out;
5557 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005558 cur_arg ++;
5559 continue;
5560 }
5561 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005562 else if (!strcmp(args[1], "offload")) {
5563 comp->offload = 1;
5564 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005565 else if (!strcmp(args[1], "type")) {
5566 int cur_arg;
5567 cur_arg = 2;
5568 if (!*args[cur_arg]) {
5569 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5570 file, linenum, args[0]);
5571 err_code |= ERR_ALERT | ERR_FATAL;
5572 goto out;
5573 }
5574 while (*(args[cur_arg])) {
5575 comp_append_type(comp, args[cur_arg]);
5576 cur_arg ++;
5577 continue;
5578 }
5579 }
5580 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005581 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005582 file, linenum, args[0]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
5586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005588 struct cfg_kw_list *kwl;
5589 int index;
5590
5591 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5592 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5593 if (kwl->kw[index].section != CFG_LISTEN)
5594 continue;
5595 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5596 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005597 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005598 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005599 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005602 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005603 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005604 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005605 err_code |= ERR_WARN;
5606 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005607 }
Willy Tarreau93893792009-07-23 13:19:11 +02005608 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005609 }
5610 }
5611 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005612
Willy Tarreau6daf3432008-01-22 16:44:08 +01005613 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005616 }
Willy Tarreau93893792009-07-23 13:19:11 +02005617 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005618 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005619 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620}
5621
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005622int
5623cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5624{
5625
5626 int err_code = 0;
5627 const char *err;
5628
5629 if (!strcmp(args[0], "userlist")) { /* new userlist */
5630 struct userlist *newul;
5631
5632 if (!*args[1]) {
5633 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5634 file, linenum, args[0]);
5635 err_code |= ERR_ALERT | ERR_FATAL;
5636 goto out;
5637 }
5638
5639 err = invalid_char(args[1]);
5640 if (err) {
5641 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5642 file, linenum, *err, args[0], args[1]);
5643 err_code |= ERR_ALERT | ERR_FATAL;
5644 goto out;
5645 }
5646
5647 for (newul = userlist; newul; newul = newul->next)
5648 if (!strcmp(newul->name, args[1])) {
5649 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5650 file, linenum, args[1]);
5651 err_code |= ERR_WARN;
5652 goto out;
5653 }
5654
5655 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5656 if (!newul) {
5657 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5658 err_code |= ERR_ALERT | ERR_ABORT;
5659 goto out;
5660 }
5661
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005662 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005663 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005664 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5665 err_code |= ERR_ALERT | ERR_ABORT;
5666 goto out;
5667 }
5668
5669 newul->next = userlist;
5670 userlist = newul;
5671
5672 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005673 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005674 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005675 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005676
5677 if (!*args[1]) {
5678 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5679 file, linenum, args[0]);
5680 err_code |= ERR_ALERT | ERR_FATAL;
5681 goto out;
5682 }
5683
5684 err = invalid_char(args[1]);
5685 if (err) {
5686 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5687 file, linenum, *err, args[0], args[1]);
5688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690 }
5691
William Lallemandfaf33152015-05-28 18:03:51 +02005692 if (!userlist)
5693 goto out;
5694
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005695 for (ag = userlist->groups; ag; ag = ag->next)
5696 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005697 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5698 file, linenum, args[1], userlist->name);
5699 err_code |= ERR_ALERT;
5700 goto out;
5701 }
5702
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005703 ag = calloc(1, sizeof(*ag));
5704 if (!ag) {
5705 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5706 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005707 goto out;
5708 }
5709
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005710 ag->name = strdup(args[1]);
5711 if (!ag) {
5712 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5713 err_code |= ERR_ALERT | ERR_ABORT;
5714 goto out;
5715 }
5716
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005717 cur_arg = 2;
5718
5719 while (*args[cur_arg]) {
5720 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005721 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005722 cur_arg += 2;
5723 continue;
5724 } else {
5725 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5726 file, linenum, args[0]);
5727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
5729 }
5730 }
5731
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005732 ag->next = userlist->groups;
5733 userlist->groups = ag;
5734
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005735 } else if (!strcmp(args[0], "user")) { /* new user */
5736 struct auth_users *newuser;
5737 int cur_arg;
5738
5739 if (!*args[1]) {
5740 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5741 file, linenum, args[0]);
5742 err_code |= ERR_ALERT | ERR_FATAL;
5743 goto out;
5744 }
William Lallemandfaf33152015-05-28 18:03:51 +02005745 if (!userlist)
5746 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005747
5748 for (newuser = userlist->users; newuser; newuser = newuser->next)
5749 if (!strcmp(newuser->user, args[1])) {
5750 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5751 file, linenum, args[1], userlist->name);
5752 err_code |= ERR_ALERT;
5753 goto out;
5754 }
5755
5756 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5757 if (!newuser) {
5758 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5759 err_code |= ERR_ALERT | ERR_ABORT;
5760 goto out;
5761 }
5762
5763 newuser->user = strdup(args[1]);
5764
5765 newuser->next = userlist->users;
5766 userlist->users = newuser;
5767
5768 cur_arg = 2;
5769
5770 while (*args[cur_arg]) {
5771 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005772#ifdef CONFIG_HAP_CRYPT
5773 if (!crypt("", args[cur_arg + 1])) {
5774 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5775 file, linenum, newuser->user);
5776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
5778 }
5779#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005780 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5781 file, linenum);
5782 err_code |= ERR_ALERT;
5783#endif
5784 newuser->pass = strdup(args[cur_arg + 1]);
5785 cur_arg += 2;
5786 continue;
5787 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5788 newuser->pass = strdup(args[cur_arg + 1]);
5789 newuser->flags |= AU_O_INSECURE;
5790 cur_arg += 2;
5791 continue;
5792 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005793 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005794 cur_arg += 2;
5795 continue;
5796 } else {
5797 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5798 file, linenum, args[0]);
5799 err_code |= ERR_ALERT | ERR_FATAL;
5800 goto out;
5801 }
5802 }
5803 } else {
5804 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5805 err_code |= ERR_ALERT | ERR_FATAL;
5806 }
5807
5808out:
5809 return err_code;
5810}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811
5812/*
5813 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005814 * Returns the error code, 0 if OK, or any combination of :
5815 * - ERR_ABORT: must abort ASAP
5816 * - ERR_FATAL: we can continue parsing but not start the service
5817 * - ERR_WARN: a warning has been emitted
5818 * - ERR_ALERT: an alert has been emitted
5819 * Only the two first ones can stop processing, the two others are just
5820 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005821 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005822int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005823{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005824 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005825 FILE *f;
5826 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005827 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005828 struct cfg_section *cs = NULL;
5829 struct cfg_section *ics;
5830
5831 /* Register internal sections */
5832 if (!cfg_register_section("listen", cfg_parse_listen) ||
5833 !cfg_register_section("frontend", cfg_parse_listen) ||
5834 !cfg_register_section("backend", cfg_parse_listen) ||
5835 !cfg_register_section("ruleset", cfg_parse_listen) ||
5836 !cfg_register_section("defaults", cfg_parse_listen) ||
5837 !cfg_register_section("global", cfg_parse_global) ||
5838 !cfg_register_section("userlist", cfg_parse_users) ||
5839 !cfg_register_section("peers", cfg_parse_peers))
5840 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005841
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 if ((f=fopen(file,"r")) == NULL)
5843 return -1;
5844
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005845 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005846 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005847 char *end;
5848 char *args[MAX_LINE_ARGS + 1];
5849 char *line = thisline;
5850
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851 linenum++;
5852
5853 end = line + strlen(line);
5854
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005855 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5856 /* Check if we reached the limit and the last char is not \n.
5857 * Watch out for the last line without the terminating '\n'!
5858 */
5859 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005860 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005861 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005862 }
5863
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005865 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005866 line++;
5867
5868 arg = 0;
5869 args[arg] = line;
5870
5871 while (*line && arg < MAX_LINE_ARGS) {
5872 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5873 * C equivalent value. Other combinations left unchanged (eg: \1).
5874 */
5875 if (*line == '\\') {
5876 int skip = 0;
5877 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5878 *line = line[1];
5879 skip = 1;
5880 }
5881 else if (line[1] == 'r') {
5882 *line = '\r';
5883 skip = 1;
5884 }
5885 else if (line[1] == 'n') {
5886 *line = '\n';
5887 skip = 1;
5888 }
5889 else if (line[1] == 't') {
5890 *line = '\t';
5891 skip = 1;
5892 }
5893 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005894 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005895 unsigned char hex1, hex2;
5896 hex1 = toupper(line[2]) - '0';
5897 hex2 = toupper(line[3]) - '0';
5898 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5899 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5900 *line = (hex1<<4) + hex2;
5901 skip = 3;
5902 }
5903 else {
5904 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005905 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005906 }
5907 }
5908 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005909 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 end -= skip;
5911 }
5912 line++;
5913 }
5914 else if (*line == '#' || *line == '\n' || *line == '\r') {
5915 /* end of string, end of loop */
5916 *line = 0;
5917 break;
5918 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005919 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005920 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005921 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005922 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 line++;
5924 args[++arg] = line;
5925 }
5926 else {
5927 line++;
5928 }
5929 }
5930
5931 /* empty line */
5932 if (!**args)
5933 continue;
5934
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005935 if (*line) {
5936 /* we had to stop due to too many args.
5937 * Let's terminate the string, print the offending part then cut the
5938 * last arg.
5939 */
5940 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5941 line++;
5942 *line = '\0';
5943
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005944 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005945 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005946 err_code |= ERR_ALERT | ERR_FATAL;
5947 args[arg] = line;
5948 }
5949
Willy Tarreau540abe42007-05-02 20:50:16 +02005950 /* zero out remaining args and ensure that at least one entry
5951 * is zeroed out.
5952 */
5953 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005954 args[arg] = line;
5955 }
5956
Willy Tarreau3842f002009-06-14 11:39:52 +02005957 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005958 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005959 char *tmp;
5960
Willy Tarreau3842f002009-06-14 11:39:52 +02005961 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005962 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005963 for (arg=0; *args[arg+1]; arg++)
5964 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005965 *tmp = '\0'; // fix the next arg to \0
5966 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005967 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005968 else if (!strcmp(args[0], "default")) {
5969 kwm = KWM_DEF;
5970 for (arg=0; *args[arg+1]; arg++)
5971 args[arg] = args[arg+1]; // shift args after inversion
5972 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005973
William Lallemand0f99e342011-10-12 17:50:54 +02005974 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5975 strcmp(args[0], "log") != 0) {
5976 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005977 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005978 }
5979
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005980 /* detect section start */
5981 list_for_each_entry(ics, &sections, list) {
5982 if (strcmp(args[0], ics->section_name) == 0) {
5983 cursection = ics->section_name;
5984 cs = ics;
5985 break;
5986 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005987 }
5988
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005990 if (cs)
5991 err_code |= cs->section_parser(file, linenum, args, kwm);
5992 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005993 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005994 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005995 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005996
5997 if (err_code & ERR_ABORT)
5998 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005999 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006000 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006001 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006002 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006003}
6004
Willy Tarreau5436afc2014-09-16 12:17:36 +02006005/* This function propagates processes from frontend <from> to backend <to> so
6006 * that it is always guaranteed that a backend pointed to by a frontend is
6007 * bound to all of its processes. After that, if the target is a "listen"
6008 * instance, the function recursively descends the target's own targets along
6009 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6010 * checked first to ensure that <to> is already bound to all processes of
6011 * <from>, there is no risk of looping and we ensure to follow the shortest
6012 * path to the destination.
6013 *
6014 * It is possible to set <to> to NULL for the first call so that the function
6015 * takes care of visiting the initial frontend in <from>.
6016 *
6017 * It is important to note that the function relies on the fact that all names
6018 * have already been resolved.
6019 */
6020void propagate_processes(struct proxy *from, struct proxy *to)
6021{
6022 struct switching_rule *rule;
6023 struct hdr_exp *exp;
6024
6025 if (to) {
6026 /* check whether we need to go down */
6027 if (from->bind_proc &&
6028 (from->bind_proc & to->bind_proc) == from->bind_proc)
6029 return;
6030
6031 if (!from->bind_proc && !to->bind_proc)
6032 return;
6033
6034 to->bind_proc = from->bind_proc ?
6035 (to->bind_proc | from->bind_proc) : 0;
6036
6037 /* now propagate down */
6038 from = to;
6039 }
6040
Willy Tarreau7110f382014-12-18 13:56:26 +01006041 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006042 return;
6043
Willy Tarreaued061c02014-12-18 14:00:43 +01006044 if (from->state == PR_STSTOPPED)
6045 return;
6046
Willy Tarreau5436afc2014-09-16 12:17:36 +02006047 /* default_backend */
6048 if (from->defbe.be)
6049 propagate_processes(from, from->defbe.be);
6050
6051 /* use_backend */
6052 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006053 if (rule->dynamic)
6054 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006055 to = rule->be.backend;
6056 propagate_processes(from, to);
6057 }
6058
6059 /* reqsetbe */
6060 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6061 if (exp->action != ACT_SETBE)
6062 continue;
6063 to = (struct proxy *)exp->replace;
6064 propagate_processes(from, to);
6065 }
6066}
6067
Willy Tarreaubb925012009-07-23 13:36:36 +02006068/*
6069 * Returns the error code, 0 if OK, or any combination of :
6070 * - ERR_ABORT: must abort ASAP
6071 * - ERR_FATAL: we can continue parsing but not start the service
6072 * - ERR_WARN: a warning has been emitted
6073 * - ERR_ALERT: an alert has been emitted
6074 * Only the two first ones can stop processing, the two others are just
6075 * indicators.
6076 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006077int check_config_validity()
6078{
6079 int cfgerr = 0;
6080 struct proxy *curproxy = NULL;
6081 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006082 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006083 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006084 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006085
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006086 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006087 /*
6088 * Now, check for the integrity of all that we have collected.
6089 */
6090
6091 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006092 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006093
Willy Tarreau193b8c62012-11-22 00:17:38 +01006094 if (!global.tune.max_http_hdr)
6095 global.tune.max_http_hdr = MAX_HTTP_HDR;
6096
6097 if (!global.tune.cookie_len)
6098 global.tune.cookie_len = CAPTURE_LEN;
6099
6100 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6101
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006102 /* Post initialisation of the users and groups lists. */
6103 err_code = userlist_postinit();
6104 if (err_code != ERR_NONE)
6105 goto out;
6106
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006107 /* first, we will invert the proxy list order */
6108 curproxy = NULL;
6109 while (proxy) {
6110 struct proxy *next;
6111
6112 next = proxy->next;
6113 proxy->next = curproxy;
6114 curproxy = proxy;
6115 if (!next)
6116 break;
6117 proxy = next;
6118 }
6119
Willy Tarreau91b00c22014-09-16 13:41:21 +02006120 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006121 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006122 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006123 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006124 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006125 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006126 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006127
Willy Tarreau050536d2012-10-04 08:47:34 +02006128 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006129 /* proxy ID not set, use automatic numbering with first
6130 * spare entry starting with next_pxid.
6131 */
6132 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6133 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6134 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006135 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006136 next_pxid++;
6137
Willy Tarreau55ea7572007-06-17 19:56:27 +02006138
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006140 /* ensure we don't keep listeners uselessly bound */
6141 stop_proxy(curproxy);
Willy Tarreaud72af0a2015-05-01 19:59:56 +02006142 free((void *)curproxy->table.peers.name);
6143 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006144 continue;
6145 }
6146
Willy Tarreau102df612014-05-07 23:56:38 +02006147 /* Check multi-process mode compatibility for the current proxy */
6148
6149 if (curproxy->bind_proc) {
6150 /* an explicit bind-process was specified, let's check how many
6151 * processes remain.
6152 */
David Carlier6de4c2f2015-07-02 07:00:17 +00006153 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02006154
6155 curproxy->bind_proc &= nbits(global.nbproc);
6156 if (!curproxy->bind_proc && nbproc == 1) {
6157 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);
6158 curproxy->bind_proc = 1;
6159 }
6160 else if (!curproxy->bind_proc && nbproc > 1) {
6161 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);
6162 curproxy->bind_proc = 0;
6163 }
6164 }
6165
Willy Tarreau3d209582014-05-09 17:06:11 +02006166 /* check and reduce the bind-proc of each listener */
6167 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6168 unsigned long mask;
6169
6170 if (!bind_conf->bind_proc)
6171 continue;
6172
6173 mask = nbits(global.nbproc);
6174 if (curproxy->bind_proc)
6175 mask &= curproxy->bind_proc;
6176 /* mask cannot be null here thanks to the previous checks */
6177
David Carlier6de4c2f2015-07-02 07:00:17 +00006178 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02006179 bind_conf->bind_proc &= mask;
6180
6181 if (!bind_conf->bind_proc && nbproc == 1) {
6182 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",
6183 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6184 bind_conf->bind_proc = mask & ~(mask - 1);
6185 }
6186 else if (!bind_conf->bind_proc && nbproc > 1) {
6187 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",
6188 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6189 bind_conf->bind_proc = 0;
6190 }
6191 }
6192
Willy Tarreauff01a212009-03-15 13:46:16 +01006193 switch (curproxy->mode) {
6194 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006195 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006196 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006197 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6198 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006199 cfgerr++;
6200 }
6201
6202 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006203 Warning("config : servers will be ignored for %s '%s'.\n",
6204 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006205 break;
6206
6207 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006208 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006209 break;
6210
6211 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006212 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006213 break;
6214 }
6215
Willy Tarreauc7c1e552015-08-11 11:36:45 +02006216 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
6217 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
6218 proxy_type_str(curproxy), curproxy->id);
6219 err_code |= ERR_WARN;
6220 }
6221
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006222 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006223 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006224 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006225 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6226 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006227 cfgerr++;
6228 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006230 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006231 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6232 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006233 cfgerr++;
6234 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006235#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006236 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006237 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6238 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006239 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006240 }
6241 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006242 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006243 /* If no LB algo is set in a backend, and we're not in
6244 * transparent mode, dispatch mode nor proxy mode, we
6245 * want to use balance roundrobin by default.
6246 */
6247 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6248 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006249 }
6250 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006251
Willy Tarreau1620ec32011-08-06 17:05:02 +02006252 if (curproxy->options & PR_O_DISPATCH)
6253 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6254 else if (curproxy->options & PR_O_HTTP_PROXY)
6255 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6256 else if (curproxy->options & PR_O_TRANSP)
6257 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006258
Willy Tarreau1620ec32011-08-06 17:05:02 +02006259 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6260 if (curproxy->options & PR_O_DISABLE404) {
6261 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6262 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6263 err_code |= ERR_WARN;
6264 curproxy->options &= ~PR_O_DISABLE404;
6265 }
6266 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6267 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6268 "send-state", proxy_type_str(curproxy), curproxy->id);
6269 err_code |= ERR_WARN;
6270 curproxy->options &= ~PR_O2_CHK_SNDST;
6271 }
Willy Tarreauef781042010-01-27 11:53:01 +01006272 }
6273
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006274 /* if a default backend was specified, let's find it */
6275 if (curproxy->defbe.name) {
6276 struct proxy *target;
6277
Alex Williams96532db2009-11-01 21:27:13 -05006278 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006279 if (!target) {
6280 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6281 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006282 cfgerr++;
6283 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006284 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6285 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006286 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006287 } else {
6288 free(curproxy->defbe.name);
6289 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006290
6291 /* Emit a warning if this proxy also has some servers */
6292 if (curproxy->srv) {
6293 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6294 curproxy->id);
6295 err_code |= ERR_WARN;
6296 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297 }
6298 }
6299
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006300 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006301 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6302 /* map jump target for ACT_SETBE in req_rep chain */
6303 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006304 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006305 struct proxy *target;
6306
Willy Tarreaua496b602006-12-17 23:15:24 +01006307 if (exp->action != ACT_SETBE)
6308 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006309
Alex Williams96532db2009-11-01 21:27:13 -05006310 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006311 if (!target) {
6312 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6313 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006314 cfgerr++;
6315 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006316 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6317 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006318 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006319 } else {
6320 free((void *)exp->replace);
6321 exp->replace = (const char *)target;
6322 }
6323 }
6324 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006325
6326 /* find the target proxy for 'use_backend' rules */
6327 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006328 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006329 struct logformat_node *node;
6330 char *pxname;
6331
6332 /* Try to parse the string as a log format expression. If the result
6333 * of the parsing is only one entry containing a simple string, then
6334 * it's a standard string corresponding to a static rule, thus the
6335 * parsing is cancelled and be.name is restored to be resolved.
6336 */
6337 pxname = rule->be.name;
6338 LIST_INIT(&rule->be.expr);
6339 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6340 curproxy->conf.args.file, curproxy->conf.args.line);
6341 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6342
6343 if (!LIST_ISEMPTY(&rule->be.expr)) {
6344 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6345 rule->dynamic = 1;
6346 free(pxname);
6347 continue;
6348 }
6349 /* simple string: free the expression and fall back to static rule */
6350 free(node->arg);
6351 free(node);
6352 }
6353
6354 rule->dynamic = 0;
6355 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006356
Alex Williams96532db2009-11-01 21:27:13 -05006357 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006358
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006359 if (!target) {
6360 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6361 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006362 cfgerr++;
6363 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006364 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6365 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006366 cfgerr++;
6367 } else {
6368 free((void *)rule->be.name);
6369 rule->be.backend = target;
6370 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006371 }
6372
Willy Tarreau5436afc2014-09-16 12:17:36 +02006373 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006374 list_for_each_entry(srule, &curproxy->server_rules, list) {
6375 struct server *target = findserver(curproxy, srule->srv.name);
6376
6377 if (!target) {
6378 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6379 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6380 cfgerr++;
6381 continue;
6382 }
6383 free((void *)srule->srv.name);
6384 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006385 }
6386
Emeric Brunb982a3d2010-01-04 15:45:53 +01006387 /* find the target table for 'stick' rules */
6388 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6389 struct proxy *target;
6390
Emeric Brun1d33b292010-01-04 15:47:17 +01006391 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6392 if (mrule->flags & STK_IS_STORE)
6393 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6394
Emeric Brunb982a3d2010-01-04 15:45:53 +01006395 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006396 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006397 else
6398 target = curproxy;
6399
6400 if (!target) {
6401 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6402 curproxy->id, mrule->table.name);
6403 cfgerr++;
6404 }
6405 else if (target->table.size == 0) {
6406 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6407 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6408 cfgerr++;
6409 }
Willy Tarreau12785782012-04-27 21:37:17 +02006410 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6411 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006412 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6413 cfgerr++;
6414 }
6415 else {
6416 free((void *)mrule->table.name);
6417 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006418 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006419 }
6420 }
6421
6422 /* find the target table for 'store response' rules */
6423 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6424 struct proxy *target;
6425
Emeric Brun1d33b292010-01-04 15:47:17 +01006426 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6427
Emeric Brunb982a3d2010-01-04 15:45:53 +01006428 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006429 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006430 else
6431 target = curproxy;
6432
6433 if (!target) {
6434 Alert("Proxy '%s': unable to find store table '%s'.\n",
6435 curproxy->id, mrule->table.name);
6436 cfgerr++;
6437 }
6438 else if (target->table.size == 0) {
6439 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6440 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6441 cfgerr++;
6442 }
Willy Tarreau12785782012-04-27 21:37:17 +02006443 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6444 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006445 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6446 cfgerr++;
6447 }
6448 else {
6449 free((void *)mrule->table.name);
6450 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006451 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006452 }
6453 }
6454
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006455 /* find the target table for 'tcp-request' layer 4 rules */
6456 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6457 struct proxy *target;
6458
Willy Tarreaub4c84932013-07-23 19:15:30 +02006459 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006460 continue;
6461
6462 if (trule->act_prm.trk_ctr.table.n)
6463 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6464 else
6465 target = curproxy;
6466
6467 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006468 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6469 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006470 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006471 cfgerr++;
6472 }
6473 else if (target->table.size == 0) {
6474 Alert("Proxy '%s': table '%s' used but not configured.\n",
6475 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6476 cfgerr++;
6477 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006478 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6479 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6480 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 +01006481 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006482 cfgerr++;
6483 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006484 else {
6485 free(trule->act_prm.trk_ctr.table.n);
6486 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006487 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006488 * to pass a list of counters to track and allocate them right here using
6489 * stktable_alloc_data_type().
6490 */
6491 }
6492 }
6493
Willy Tarreaud1f96522010-08-03 19:34:32 +02006494 /* find the target table for 'tcp-request' layer 6 rules */
6495 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6496 struct proxy *target;
6497
Willy Tarreaub4c84932013-07-23 19:15:30 +02006498 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006499 continue;
6500
6501 if (trule->act_prm.trk_ctr.table.n)
6502 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6503 else
6504 target = curproxy;
6505
6506 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006507 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6508 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006509 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006510 cfgerr++;
6511 }
6512 else if (target->table.size == 0) {
6513 Alert("Proxy '%s': table '%s' used but not configured.\n",
6514 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6515 cfgerr++;
6516 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006517 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6518 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6519 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 +01006520 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006521 cfgerr++;
6522 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006523 else {
6524 free(trule->act_prm.trk_ctr.table.n);
6525 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006526 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006527 * to pass a list of counters to track and allocate them right here using
6528 * stktable_alloc_data_type().
6529 */
6530 }
6531 }
6532
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006533 /* move any "block" rules at the beginning of the http-request rules */
6534 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6535 /* insert block_rules into http_req_rules at the beginning */
6536 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6537 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6538 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6539 curproxy->http_req_rules.n = curproxy->block_rules.n;
6540 LIST_INIT(&curproxy->block_rules);
6541 }
6542
Emeric Brun32da3c42010-09-23 18:39:19 +02006543 if (curproxy->table.peers.name) {
6544 struct peers *curpeers = peers;
6545
6546 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6547 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6548 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006549 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006550 break;
6551 }
6552 }
6553
6554 if (!curpeers) {
6555 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6556 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006557 free((void *)curproxy->table.peers.name);
6558 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006559 cfgerr++;
6560 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02006561 else if (curpeers->state == PR_STSTOPPED) {
6562 /* silently disable this peers section */
6563 curproxy->table.peers.p = NULL;
6564 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006565 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006566 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6567 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006568 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006569 cfgerr++;
6570 }
6571 }
6572
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006573 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006574 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006575 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6576 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6577 "proxy", curproxy->id);
6578 cfgerr++;
6579 goto out_uri_auth_compat;
6580 }
6581
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006582 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006583 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006584 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006585 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006586
Willy Tarreau95fa4692010-02-01 13:05:50 +01006587 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6588 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006589
6590 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006591 uri_auth_compat_req[i++] = "realm";
6592 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6593 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006594
Willy Tarreau95fa4692010-02-01 13:05:50 +01006595 uri_auth_compat_req[i++] = "unless";
6596 uri_auth_compat_req[i++] = "{";
6597 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6598 uri_auth_compat_req[i++] = "}";
6599 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006600
Willy Tarreauff011f22011-01-06 17:51:27 +01006601 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6602 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006603 cfgerr++;
6604 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006605 }
6606
Willy Tarreauff011f22011-01-06 17:51:27 +01006607 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006608
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006609 if (curproxy->uri_auth->auth_realm) {
6610 free(curproxy->uri_auth->auth_realm);
6611 curproxy->uri_auth->auth_realm = NULL;
6612 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006613
6614 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006615 }
6616out_uri_auth_compat:
6617
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006618 /* compile the log format */
6619 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006620 if (curproxy->conf.logformat_string != default_http_log_format &&
6621 curproxy->conf.logformat_string != default_tcp_log_format &&
6622 curproxy->conf.logformat_string != clf_http_log_format)
6623 free(curproxy->conf.logformat_string);
6624 curproxy->conf.logformat_string = NULL;
6625 free(curproxy->conf.lfs_file);
6626 curproxy->conf.lfs_file = NULL;
6627 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006628 }
6629
Willy Tarreau62a61232013-04-12 18:13:46 +02006630 if (curproxy->conf.logformat_string) {
6631 curproxy->conf.args.ctx = ARGC_LOG;
6632 curproxy->conf.args.file = curproxy->conf.lfs_file;
6633 curproxy->conf.args.line = curproxy->conf.lfs_line;
6634 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006635 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006636 curproxy->conf.args.file = NULL;
6637 curproxy->conf.args.line = 0;
6638 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006639
Willy Tarreau62a61232013-04-12 18:13:46 +02006640 if (curproxy->conf.uniqueid_format_string) {
6641 curproxy->conf.args.ctx = ARGC_UIF;
6642 curproxy->conf.args.file = curproxy->conf.uif_file;
6643 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006644 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006645 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006646 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006647 curproxy->conf.args.file = NULL;
6648 curproxy->conf.args.line = 0;
6649 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006650
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006651 /* only now we can check if some args remain unresolved.
6652 * This must be done after the users and groups resolution.
6653 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006654 cfgerr += smp_resolve_args(curproxy);
6655 if (!cfgerr)
6656 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006657
Willy Tarreau2738a142006-07-08 17:28:09 +02006658 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006659 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006660 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006661 (!curproxy->timeout.connect ||
6662 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006663 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006664 " | While not properly invalid, you will certainly encounter various problems\n"
6665 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006666 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006667 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006668 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006669 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006670
Willy Tarreau1fa31262007-12-03 00:36:16 +01006671 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6672 * We must still support older configurations, so let's find out whether those
6673 * parameters have been set or must be copied from contimeouts.
6674 */
6675 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006676 if (!curproxy->timeout.tarpit ||
6677 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006678 /* tarpit timeout not set. We search in the following order:
6679 * default.tarpit, curr.connect, default.connect.
6680 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006681 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006682 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006683 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006684 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006685 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006686 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006687 }
6688 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006689 (!curproxy->timeout.queue ||
6690 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006691 /* queue timeout not set. We search in the following order:
6692 * default.queue, curr.connect, default.connect.
6693 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006694 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006695 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006696 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006697 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006698 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006699 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006700 }
6701 }
6702
Willy Tarreau1620ec32011-08-06 17:05:02 +02006703 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006704 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6705 curproxy->check_req = (char *)malloc(curproxy->check_len);
6706 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006707 }
6708
Willy Tarreau215663d2014-06-13 18:30:23 +02006709 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6710 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6711 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6712 proxy_type_str(curproxy), curproxy->id);
6713 err_code |= ERR_WARN;
6714 }
6715
Willy Tarreau193b8c62012-11-22 00:17:38 +01006716 /* ensure that cookie capture length is not too large */
6717 if (curproxy->capture_len >= global.tune.cookie_len) {
6718 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6719 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6720 err_code |= ERR_WARN;
6721 curproxy->capture_len = global.tune.cookie_len - 1;
6722 }
6723
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006724 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006725 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006726 curproxy->req_cap_pool = create_pool("ptrcap",
6727 curproxy->nb_req_cap * sizeof(char *),
6728 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006729 }
6730
6731 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006732 curproxy->rsp_cap_pool = create_pool("ptrcap",
6733 curproxy->nb_rsp_cap * sizeof(char *),
6734 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006735 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006736
Willy Tarreaubaaee002006-06-26 02:48:02 +02006737 /* first, we will invert the servers list order */
6738 newsrv = NULL;
6739 while (curproxy->srv) {
6740 struct server *next;
6741
6742 next = curproxy->srv->next;
6743 curproxy->srv->next = newsrv;
6744 newsrv = curproxy->srv;
6745 if (!next)
6746 break;
6747 curproxy->srv = next;
6748 }
6749
Willy Tarreau17edc812014-01-03 12:14:34 +01006750 /* Check that no server name conflicts. This causes trouble in the stats.
6751 * We only emit a warning for the first conflict affecting each server,
6752 * in order to avoid combinatory explosion if all servers have the same
6753 * name. We do that only for servers which do not have an explicit ID,
6754 * because these IDs were made also for distinguishing them and we don't
6755 * want to annoy people who correctly manage them.
6756 */
6757 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6758 struct server *other_srv;
6759
6760 if (newsrv->puid)
6761 continue;
6762
6763 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6764 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6765 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6766 newsrv->conf.file, newsrv->conf.line,
6767 proxy_type_str(curproxy), curproxy->id,
6768 newsrv->id, other_srv->conf.line);
6769 break;
6770 }
6771 }
6772 }
6773
Willy Tarreaudd701652010-05-25 23:03:02 +02006774 /* assign automatic UIDs to servers which don't have one yet */
6775 next_id = 1;
6776 newsrv = curproxy->srv;
6777 while (newsrv != NULL) {
6778 if (!newsrv->puid) {
6779 /* server ID not set, use automatic numbering with first
6780 * spare entry starting with next_svid.
6781 */
6782 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6783 newsrv->conf.id.key = newsrv->puid = next_id;
6784 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6785 }
6786 next_id++;
6787 newsrv = newsrv->next;
6788 }
6789
Willy Tarreau20697042007-11-15 23:26:18 +01006790 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006791 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006792
Willy Tarreau62c3be22012-01-20 13:12:32 +01006793 /*
6794 * If this server supports a maxconn parameter, it needs a dedicated
6795 * tasks to fill the emptied slots when a connection leaves.
6796 * Also, resolve deferred tracking dependency if needed.
6797 */
6798 newsrv = curproxy->srv;
6799 while (newsrv != NULL) {
6800 if (newsrv->minconn > newsrv->maxconn) {
6801 /* Only 'minconn' was specified, or it was higher than or equal
6802 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6803 * this will avoid further useless expensive computations.
6804 */
6805 newsrv->maxconn = newsrv->minconn;
6806 } else if (newsrv->maxconn && !newsrv->minconn) {
6807 /* minconn was not specified, so we set it to maxconn */
6808 newsrv->minconn = newsrv->maxconn;
6809 }
6810
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006811#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006812 if (newsrv->use_ssl || newsrv->check.use_ssl)
6813 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006814#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006815
Willy Tarreau2f075e92013-12-03 11:11:34 +01006816 /* set the check type on the server */
6817 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6818
Willy Tarreau62c3be22012-01-20 13:12:32 +01006819 if (newsrv->trackit) {
6820 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006821 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006822 char *pname, *sname;
6823
6824 pname = newsrv->trackit;
6825 sname = strrchr(pname, '/');
6826
6827 if (sname)
6828 *sname++ = '\0';
6829 else {
6830 sname = pname;
6831 pname = NULL;
6832 }
6833
6834 if (pname) {
6835 px = findproxy(pname, PR_CAP_BE);
6836 if (!px) {
6837 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6838 proxy_type_str(curproxy), curproxy->id,
6839 newsrv->id, pname);
6840 cfgerr++;
6841 goto next_srv;
6842 }
6843 } else
6844 px = curproxy;
6845
6846 srv = findserver(px, sname);
6847 if (!srv) {
6848 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6849 proxy_type_str(curproxy), curproxy->id,
6850 newsrv->id, sname);
6851 cfgerr++;
6852 goto next_srv;
6853 }
6854
Willy Tarreau32091232014-05-16 13:52:00 +02006855 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6856 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6857 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006858 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006859 "tracking as it does not have any check nor agent enabled.\n",
6860 proxy_type_str(curproxy), curproxy->id,
6861 newsrv->id, px->id, srv->id);
6862 cfgerr++;
6863 goto next_srv;
6864 }
6865
6866 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6867
6868 if (loop) {
6869 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6870 "belongs to a tracking chain looping back to %s/%s.\n",
6871 proxy_type_str(curproxy), curproxy->id,
6872 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006873 cfgerr++;
6874 goto next_srv;
6875 }
6876
6877 if (curproxy != px &&
6878 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6879 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6880 "tracking: disable-on-404 option inconsistency.\n",
6881 proxy_type_str(curproxy), curproxy->id,
6882 newsrv->id, px->id, srv->id);
6883 cfgerr++;
6884 goto next_srv;
6885 }
6886
6887 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006888 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006889 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006890 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006891 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006892 }
6893
6894 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006895 newsrv->tracknext = srv->trackers;
6896 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006897
6898 free(newsrv->trackit);
6899 newsrv->trackit = NULL;
6900 }
6901 next_srv:
6902 newsrv = newsrv->next;
6903 }
6904
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006905 /* We have to initialize the server lookup mechanism depending
6906 * on what LB algorithm was choosen.
6907 */
6908
6909 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6910 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6911 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006912 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6913 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6914 init_server_map(curproxy);
6915 } else {
6916 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6917 fwrr_init_server_groups(curproxy);
6918 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006919 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006920
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006921 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006922 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6923 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6924 fwlc_init_server_tree(curproxy);
6925 } else {
6926 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6927 fas_init_server_tree(curproxy);
6928 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006929 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006930
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006931 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006932 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6933 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6934 chash_init_server_tree(curproxy);
6935 } else {
6936 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6937 init_server_map(curproxy);
6938 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006939 break;
6940 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006941
6942 if (curproxy->options & PR_O_LOGASAP)
6943 curproxy->to_log &= ~LW_BYTES;
6944
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006945 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006946 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006947 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6948 proxy_type_str(curproxy), curproxy->id);
6949 err_code |= ERR_WARN;
6950 }
6951
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006952 if (curproxy->mode != PR_MODE_HTTP) {
6953 int optnum;
6954
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006955 if (curproxy->uri_auth) {
6956 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6957 proxy_type_str(curproxy), curproxy->id);
6958 err_code |= ERR_WARN;
6959 curproxy->uri_auth = NULL;
6960 }
6961
Willy Tarreau87cf5142011-08-19 22:57:24 +02006962 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006963 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6964 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6965 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006966 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006967 }
6968
6969 if (curproxy->options & PR_O_ORGTO) {
6970 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6971 "originalto", proxy_type_str(curproxy), curproxy->id);
6972 err_code |= ERR_WARN;
6973 curproxy->options &= ~PR_O_ORGTO;
6974 }
6975
6976 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6977 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6978 (curproxy->cap & cfg_opts[optnum].cap) &&
6979 (curproxy->options & cfg_opts[optnum].val)) {
6980 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6981 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6982 err_code |= ERR_WARN;
6983 curproxy->options &= ~cfg_opts[optnum].val;
6984 }
6985 }
6986
6987 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6988 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6989 (curproxy->cap & cfg_opts2[optnum].cap) &&
6990 (curproxy->options2 & cfg_opts2[optnum].val)) {
6991 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6992 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6993 err_code |= ERR_WARN;
6994 curproxy->options2 &= ~cfg_opts2[optnum].val;
6995 }
6996 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006997
Pieter Baauwd551fb52013-05-08 22:49:23 +02006998#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006999 if (curproxy->conn_src.bind_hdr_occ) {
7000 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007001 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007002 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007003 err_code |= ERR_WARN;
7004 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007005#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007006 }
7007
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007009 * ensure that we're not cross-dressing a TCP server into HTTP.
7010 */
7011 newsrv = curproxy->srv;
7012 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007013 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007014 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7015 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007016 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007017 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007018
Willy Tarreau0cec3312011-10-31 13:49:26 +01007019 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7020 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7021 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7022 err_code |= ERR_WARN;
7023 }
7024
Willy Tarreauc93cd162014-05-13 15:54:22 +02007025 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007026 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7027 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7028 err_code |= ERR_WARN;
7029 }
7030
Pieter Baauwd551fb52013-05-08 22:49:23 +02007031#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007032 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7033 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007034 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 +01007035 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007036 err_code |= ERR_WARN;
7037 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007038#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007039 newsrv = newsrv->next;
7040 }
7041
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007042 /* check if we have a frontend with "tcp-request content" looking at L7
7043 * with no inspect-delay
7044 */
7045 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7046 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7047 if (trule->action == TCP_ACT_CAPTURE &&
7048 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7049 break;
7050 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7051 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7052 break;
7053 }
7054
7055 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7056 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7057 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7058 " This means that these rules will randomly find their contents. This can be fixed by"
7059 " setting the tcp-request inspect-delay.\n",
7060 proxy_type_str(curproxy), curproxy->id);
7061 err_code |= ERR_WARN;
7062 }
7063 }
7064
Willy Tarreauc1a21672009-08-16 22:37:44 +02007065 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007066 if (!curproxy->accept)
7067 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007068
Willy Tarreauc1a21672009-08-16 22:37:44 +02007069 if (curproxy->tcp_req.inspect_delay ||
7070 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007071 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007072
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007073 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007074 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007075 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007076 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007077
7078 /* both TCP and HTTP must check switching rules */
7079 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7080 }
7081
7082 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007083 if (curproxy->tcp_req.inspect_delay ||
7084 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7085 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7086
Emeric Brun97679e72010-09-23 17:56:44 +02007087 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7088 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7089
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007090 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007091 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007092 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007093 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007094
7095 /* If the backend does requires RDP cookie persistence, we have to
7096 * enable the corresponding analyser.
7097 */
7098 if (curproxy->options2 & PR_O2_RDPC_PRST)
7099 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7100 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007101 }
7102
7103 /***********************************************************/
7104 /* At this point, target names have already been resolved. */
7105 /***********************************************************/
7106
7107 /* Check multi-process mode compatibility */
7108
7109 if (global.nbproc > 1 && global.stats_fe) {
7110 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7111 unsigned long mask;
7112
7113 mask = nbits(global.nbproc);
7114 if (global.stats_fe->bind_proc)
7115 mask &= global.stats_fe->bind_proc;
7116
7117 if (bind_conf->bind_proc)
7118 mask &= bind_conf->bind_proc;
7119
7120 /* stop here if more than one process is used */
David Carlier6de4c2f2015-07-02 07:00:17 +00007121 if (my_popcountl(mask) > 1)
Willy Tarreau91b00c22014-09-16 13:41:21 +02007122 break;
7123 }
7124 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7125 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");
7126 }
7127 }
7128
7129 /* Make each frontend inherit bind-process from its listeners when not specified. */
7130 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7131 if (curproxy->bind_proc)
7132 continue;
7133
7134 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7135 unsigned long mask;
7136
Willy Tarreau01760ad2015-05-04 21:57:58 +02007137 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007138 curproxy->bind_proc |= mask;
7139 }
7140
7141 if (!curproxy->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007142 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007143 }
7144
7145 if (global.stats_fe) {
7146 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7147 unsigned long mask;
7148
Cyril Bonté32e4f252016-02-24 00:14:54 +01007149 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau91b00c22014-09-16 13:41:21 +02007150 global.stats_fe->bind_proc |= mask;
7151 }
7152 if (!global.stats_fe->bind_proc)
Willy Tarreau01760ad2015-05-04 21:57:58 +02007153 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007154 }
7155
Willy Tarreaub3228c82014-10-01 20:50:17 +02007156 /* propagate bindings from frontends to backends. Don't do it if there
7157 * are any fatal errors as we must not call it with unresolved proxies.
7158 */
7159 if (!cfgerr) {
7160 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7161 if (curproxy->cap & PR_CAP_FE)
7162 propagate_processes(curproxy, NULL);
7163 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007164 }
7165
7166 /* Bind each unbound backend to all processes when not specified. */
7167 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7168 if (curproxy->bind_proc)
7169 continue;
Willy Tarreau01760ad2015-05-04 21:57:58 +02007170 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau91b00c22014-09-16 13:41:21 +02007171 }
7172
7173 /*******************************************************/
7174 /* At this step, all proxies have a non-null bind_proc */
7175 /*******************************************************/
7176
7177 /* perform the final checks before creating tasks */
7178
7179 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7180 struct listener *listener;
7181 unsigned int next_id;
7182 int nbproc;
7183
David Carlier6de4c2f2015-07-02 07:00:17 +00007184 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007185
Emeric Brunc52962f2012-11-15 18:28:02 +01007186#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007187 /* Configure SSL for each bind line.
7188 * Note: if configuration fails at some point, the ->ctx member
7189 * remains NULL so that listeners can later detach.
7190 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007191 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007192 int alloc_ctx;
7193
Emeric Brunc52962f2012-11-15 18:28:02 +01007194 if (!bind_conf->is_ssl) {
7195 if (bind_conf->default_ctx) {
7196 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7197 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7198 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007199 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007200 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007201 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007202 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007203 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007204 cfgerr++;
7205 continue;
7206 }
7207
Emeric Brun8dc60392014-05-09 13:52:00 +02007208 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007209 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007210 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7211 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");
7212 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007213 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007214 cfgerr++;
7215 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007216 }
7217
Emeric Brunfc0421f2012-09-07 17:30:07 +02007218 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007219 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007220 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007221#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007222
Willy Tarreaue6b98942007-10-29 01:09:36 +01007223 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007224 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007225 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007226 if (!listener->luid) {
7227 /* listener ID not set, use automatic numbering with first
7228 * spare entry starting with next_luid.
7229 */
7230 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7231 listener->conf.id.key = listener->luid = next_id;
7232 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007233 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007234 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007235
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007236 /* enable separate counters */
7237 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7238 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007239 if (!listener->name)
7240 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007241 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007242
Willy Tarreaue6b98942007-10-29 01:09:36 +01007243 if (curproxy->options & PR_O_TCP_NOLING)
7244 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007245 if (!listener->maxconn)
7246 listener->maxconn = curproxy->maxconn;
7247 if (!listener->backlog)
7248 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007249 if (!listener->maxaccept)
7250 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7251
7252 /* we want to have an optimal behaviour on single process mode to
7253 * maximize the work at once, but in multi-process we want to keep
7254 * some fairness between processes, so we target half of the max
7255 * number of events to be balanced over all the processes the proxy
7256 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7257 * used to disable the limit.
7258 */
7259 if (listener->maxaccept > 0) {
7260 if (nbproc > 1)
7261 listener->maxaccept = (listener->maxaccept + 1) / 2;
7262 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7263 }
7264
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007265 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007266 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007267 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007268 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007269
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007270 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7271 listener->options |= LI_O_TCP_RULES;
7272
Willy Tarreaude3041d2010-05-31 10:56:17 +02007273 if (curproxy->mon_mask.s_addr)
7274 listener->options |= LI_O_CHK_MONNET;
7275
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007276 /* smart accept mode is automatic in HTTP mode */
7277 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007278 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007279 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7280 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007281 }
7282
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007283 /* Release unused SSL configs */
7284 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7285 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007286 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007287#ifdef USE_OPENSSL
7288 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007289 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007290 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007291 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007292 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007293#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007294 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007295
Willy Tarreau102df612014-05-07 23:56:38 +02007296 if (nbproc > 1) {
7297 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007298 int count, maxproc = 0;
7299
7300 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carlier6de4c2f2015-07-02 07:00:17 +00007301 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreau036a83e2014-09-16 15:11:04 +02007302 if (count > maxproc)
7303 maxproc = count;
7304 }
7305 /* backends have 0, frontends have 1 or more */
7306 if (maxproc != 1)
7307 Warning("Proxy '%s': in multi-process mode, stats will be"
7308 " limited to process assigned to the current request.\n",
7309 curproxy->id);
7310
Willy Tarreau102df612014-05-07 23:56:38 +02007311 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7312 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7313 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007314 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007315 }
Willy Tarreau102df612014-05-07 23:56:38 +02007316 if (curproxy->appsession_name) {
7317 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7318 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007319 }
Willy Tarreau102df612014-05-07 23:56:38 +02007320 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7321 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7322 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007323 }
7324 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007325
7326 /* create the task associated with the proxy */
7327 curproxy->task = task_new();
7328 if (curproxy->task) {
7329 curproxy->task->context = curproxy;
7330 curproxy->task->process = manage_proxy;
7331 /* no need to queue, it will be done automatically if some
7332 * listener gets limited.
7333 */
7334 curproxy->task->expire = TICK_ETERNITY;
7335 } else {
7336 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7337 curproxy->id);
7338 cfgerr++;
7339 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007340 }
7341
Willy Tarreaufbb78422011-06-05 15:38:35 +02007342 /* automatically compute fullconn if not set. We must not do it in the
7343 * loop above because cross-references are not yet fully resolved.
7344 */
7345 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7346 /* If <fullconn> is not set, let's set it to 10% of the sum of
7347 * the possible incoming frontend's maxconns.
7348 */
7349 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7350 struct proxy *fe;
7351 int total = 0;
7352
7353 /* sum up the number of maxconns of frontends which
7354 * reference this backend at least once or which are
7355 * the same one ('listen').
7356 */
7357 for (fe = proxy; fe; fe = fe->next) {
7358 struct switching_rule *rule;
7359 struct hdr_exp *exp;
7360 int found = 0;
7361
7362 if (!(fe->cap & PR_CAP_FE))
7363 continue;
7364
7365 if (fe == curproxy) /* we're on a "listen" instance */
7366 found = 1;
7367
7368 if (fe->defbe.be == curproxy) /* "default_backend" */
7369 found = 1;
7370
7371 /* check if a "use_backend" rule matches */
7372 if (!found) {
7373 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007374 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007375 found = 1;
7376 break;
7377 }
7378 }
7379 }
7380
7381 /* check if a "reqsetbe" rule matches */
7382 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7383 if (exp->action == ACT_SETBE &&
7384 (struct proxy *)exp->replace == curproxy) {
7385 found = 1;
7386 break;
7387 }
7388 }
7389
7390 /* now we've checked all possible ways to reference a backend
7391 * from a frontend.
7392 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007393 if (!found)
7394 continue;
7395 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007396 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007397 /* we have the sum of the maxconns in <total>. We only
7398 * keep 10% of that sum to set the default fullconn, with
7399 * a hard minimum of 1 (to avoid a divide by zero).
7400 */
7401 curproxy->fullconn = (total + 9) / 10;
7402 if (!curproxy->fullconn)
7403 curproxy->fullconn = 1;
7404 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007405 }
7406
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007407 /*
7408 * Recount currently required checks.
7409 */
7410
7411 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7412 int optnum;
7413
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007414 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7415 if (curproxy->options & cfg_opts[optnum].val)
7416 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007417
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007418 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7419 if (curproxy->options2 & cfg_opts2[optnum].val)
7420 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007421 }
7422
Willy Tarreaucdb5e922015-05-01 19:12:05 +02007423 /* compute the required process bindings for the peers */
7424 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
7425 if (curproxy->table.peers.p)
7426 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
7427
Willy Tarreau122541c2011-09-07 21:24:49 +02007428 if (peers) {
7429 struct peers *curpeers = peers, **last;
7430 struct peer *p, *pb;
7431
Willy Tarreauab0419d2015-05-01 19:15:17 +02007432 /* Remove all peers sections which don't have a valid listener,
7433 * which are not used by any table, or which are bound to more
7434 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02007435 */
7436 last = &peers;
7437 while (*last) {
7438 curpeers = *last;
Willy Tarreau34d05b02015-05-01 20:02:17 +02007439
7440 if (curpeers->state == PR_STSTOPPED) {
7441 /* the "disabled" keyword was present */
7442 if (curpeers->peers_fe)
7443 stop_proxy(curpeers->peers_fe);
7444 curpeers->peers_fe = NULL;
7445 }
7446 else if (!curpeers->peers_fe) {
7447 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7448 curpeers->id, localpeer);
7449 }
David Carlier6de4c2f2015-07-02 07:00:17 +00007450 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreauab0419d2015-05-01 19:15:17 +02007451 /* either it's totally stopped or too much used */
7452 if (curpeers->peers_fe->bind_proc) {
7453 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreaua5d7d072015-05-04 21:48:51 +02007454 "running in different processes (%d different ones). "
7455 "Check global.nbproc and all tables' bind-process "
David Carlier6de4c2f2015-07-02 07:00:17 +00007456 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreauab0419d2015-05-01 19:15:17 +02007457 cfgerr++;
7458 }
7459 stop_proxy(curpeers->peers_fe);
7460 curpeers->peers_fe = NULL;
7461 }
Willy Tarreau34d05b02015-05-01 20:02:17 +02007462 else {
Willy Tarreau122541c2011-09-07 21:24:49 +02007463 last = &curpeers->next;
7464 continue;
7465 }
7466
Willy Tarreau34d05b02015-05-01 20:02:17 +02007467 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02007468 p = curpeers->remote;
7469 while (p) {
7470 pb = p->next;
7471 free(p->id);
7472 free(p);
7473 p = pb;
7474 }
7475
7476 /* Destroy and unlink this curpeers section.
7477 * Note: curpeers is backed up into *last.
7478 */
7479 free(curpeers->id);
7480 curpeers = curpeers->next;
7481 free(*last);
7482 *last = curpeers;
7483 }
7484 }
7485
Willy Tarreauf2df7ef2015-05-01 19:09:08 +02007486 /* initialize stick-tables on backend capable proxies. This must not
7487 * be done earlier because the data size may be discovered while parsing
7488 * other proxies.
7489 */
7490 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7491 if (curproxy->state == PR_STSTOPPED)
7492 continue;
7493
7494 if (!stktable_init(&curproxy->table)) {
7495 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7496 cfgerr++;
7497 }
7498 }
7499
Willy Tarreau34eb6712011-10-24 18:15:04 +02007500 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007501 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007502 MEM_F_SHARED);
7503
Willy Tarreaubb925012009-07-23 13:36:36 +02007504 if (cfgerr > 0)
7505 err_code |= ERR_ALERT | ERR_FATAL;
7506 out:
7507 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007508}
7509
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007510/*
7511 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7512 * parsing sessions.
7513 */
7514void cfg_register_keywords(struct cfg_kw_list *kwl)
7515{
7516 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7517}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007518
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007519/*
7520 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7521 */
7522void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7523{
7524 LIST_DEL(&kwl->list);
7525 LIST_INIT(&kwl->list);
7526}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007527
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007528/* this function register new section in the haproxy configuration file.
7529 * <section_name> is the name of this new section and <section_parser>
7530 * is the called parser. If two section declaration have the same name,
7531 * only the first declared is used.
7532 */
7533int cfg_register_section(char *section_name,
7534 int (*section_parser)(const char *, int, char **, int))
7535{
7536 struct cfg_section *cs;
7537
7538 cs = calloc(1, sizeof(*cs));
7539 if (!cs) {
7540 Alert("register section '%s': out of memory.\n", section_name);
7541 return 0;
7542 }
7543
7544 cs->section_name = section_name;
7545 cs->section_parser = section_parser;
7546
7547 LIST_ADDQ(&sections, &cs->list);
7548
7549 return 1;
7550}
7551
Willy Tarreaubaaee002006-06-26 02:48:02 +02007552/*
7553 * Local variables:
7554 * c-indent-level: 8
7555 * c-basic-offset: 8
7556 * End:
7557 */