blob: 750c5ac7fc8b2ba155cf6b01466dabf52f9d6db9 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté2c8d7002014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020044
45#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020046#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020047#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010048#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020049#include <types/peers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020050
Willy Tarreaueb0c6142007-05-07 00:53:22 +020051#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010052#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020054#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020056#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020057#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020058#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020059#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020060#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010061#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020062#include <proto/lb_fwlc.h>
63#include <proto/lb_fwrr.h>
64#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020065#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020066#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010068#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020069#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010071#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020072#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020073#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020074#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010075#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020076#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010078#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079
Emeric Brunfc0421f2012-09-07 17:30:07 +020080#ifdef USE_OPENSSL
81#include <types/ssl_sock.h>
82#include <proto/ssl_sock.h>
83#include <proto/shctx.h>
84#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Willy Tarreauf3c69202006-07-09 16:42:34 +020086/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
87 * ssl-hello-chk option to ensure that the remote server speaks SSL.
88 *
89 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
90 */
91const char sslv3_client_hello_pkt[] = {
92 "\x16" /* ContentType : 0x16 = Hanshake */
93 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
94 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
95 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
96 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
97 "\x03\x00" /* Hello Version : 0x0300 = v3 */
98 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
99 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
100 "\x00" /* Session ID length : empty (no session ID) */
101 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
102 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
103 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
104 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
105 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
106 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
107 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
108 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
109 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
110 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
111 "\x00\x38" "\x00\x39" "\x00\x3A"
112 "\x01" /* Compression Length : 0x01 = 1 byte for types */
113 "\x00" /* Compression Type : 0x00 = NULL compression */
114};
115
Willy Tarreau3842f002009-06-14 11:39:52 +0200116/* various keyword modifiers */
117enum kw_mod {
118 KWM_STD = 0, /* normal */
119 KWM_NO, /* "no" prefixed before the keyword */
120 KWM_DEF, /* "default" prefixed before the keyword */
121};
122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100123/* permit to store configuration section */
124struct cfg_section {
125 struct list list;
126 char *section_name;
127 int (*section_parser)(const char *, int, char **, int);
128};
129
130/* Used to chain configuration sections definitions. This list
131 * stores struct cfg_section
132 */
133struct list sections = LIST_HEAD_INIT(sections);
134
Willy Tarreau13943ab2006-12-31 00:24:10 +0100135/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100136struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137 const char *name;
138 unsigned int val;
139 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100140 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100141 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142};
143
144/* proxy->options */
145static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100146{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
148 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
149 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
150 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
151 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
152 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau1c3a6122015-05-01 15:37:53 +0200154 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100155 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
157 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
158 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
159 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
160 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100161#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100162 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100163#else
164 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100165#endif
166
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100167 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100168};
169
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100170/* proxy->options2 */
171static const struct cfg_opt cfg_opts2[] =
172{
173#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100174 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
175 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100177#else
178 { "splice-request", 0, 0, 0, 0 },
179 { "splice-response", 0, 0, 0, 0 },
180 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100181#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100182 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
183 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
184 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
185 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
186 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
187 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
188 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
190 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400191 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100192 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200193 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200194 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100195 { NULL, 0, 0, 0 }
196};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200197
Willy Tarreau6daf3432008-01-22 16:44:08 +0100198static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200199static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
200int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100201int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200203/* List head of all known configuration keywords */
204static struct cfg_kw_list cfg_keywords = {
205 .list = LIST_HEAD_INIT(cfg_keywords.list)
206};
207
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208/*
209 * converts <str> to a list of listeners which are dynamically allocated.
210 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
211 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
212 * - <port> is a numerical port from 1 to 65535 ;
213 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
214 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200215 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
216 * not NULL, it must be a valid pointer to either NULL or a freeable area that
217 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200218 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200220{
221 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100222 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200223 int port, end;
224
225 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200226
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100228 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100229 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230
231 str = next;
232 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100233 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234 *next++ = 0;
235 }
236
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100237 ss2 = str2sa_range(str, &port, &end, err,
238 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
239 if (!ss2)
240 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200241
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100242 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100243 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200244 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100245 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200247
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100248 if (!port || !end) {
249 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
250 goto fail;
251 }
252
Emeric Bruned760922010-10-22 17:59:25 +0200253 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200254 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200255 goto fail;
256 }
257
258 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200259 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200260 goto fail;
261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200262 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100263 else if (ss2->ss_family == AF_UNSPEC) {
264 socklen_t addr_len;
265
266 /* We want to attach to an already bound fd whose number
267 * is in the addr part of ss2 when cast to sockaddr_in.
268 * Note that by definition there is a single listener.
269 * We still have to determine the address family to
270 * register the correct protocol.
271 */
272 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
273 addr_len = sizeof(*ss2);
274 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
275 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
276 goto fail;
277 }
278
279 port = end = get_host_port(ss2);
280 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200281
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100282 /* OK the address looks correct */
283 ss = *ss2;
284
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285 for (; port <= end; port++) {
286 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100287 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200288 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
289 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
290 l->frontend = curproxy;
291 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292
Willy Tarreau40aa0702013-03-10 23:51:38 +0100293 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200294 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200295 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100296 l->state = LI_INIT;
297
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100298 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 tcpv4_add_listener(l);
301 }
Emeric Bruned760922010-10-22 17:59:25 +0200302 else if (ss.ss_family == AF_INET6) {
303 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
304 tcpv6_add_listener(l);
305 }
306 else {
Emeric Bruned760922010-10-22 17:59:25 +0200307 uxst_add_listener(l);
308 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200309
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200310 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100311 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200312 } /* end for(port) */
313 } /* end while(next) */
314 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200315 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 fail:
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319}
320
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200321/* Report a warning if a rule is placed after a 'tcp-request content' rule.
322 * Return 1 if the warning has been emitted, otherwise 0.
323 */
324int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
325{
326 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
327 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
328 file, line, arg);
329 return 1;
330 }
331 return 0;
332}
333
Willy Tarreau61d18892009-03-31 10:49:21 +0200334/* Report a warning if a rule is placed after a 'block' rule.
335 * Return 1 if the warning has been emitted, otherwise 0.
336 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100337int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200338{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200339 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200340 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
341 file, line, arg);
342 return 1;
343 }
344 return 0;
345}
346
Willy Tarreau5002f572014-04-23 01:32:02 +0200347/* Report a warning if a rule is placed after an 'http_request' rule.
348 * Return 1 if the warning has been emitted, otherwise 0.
349 */
350int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
351{
352 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
353 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
354 file, line, arg);
355 return 1;
356 }
357 return 0;
358}
359
Willy Tarreau61d18892009-03-31 10:49:21 +0200360/* Report a warning if a rule is placed after a reqrewrite rule.
361 * Return 1 if the warning has been emitted, otherwise 0.
362 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100363int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200364{
365 if (proxy->req_exp) {
366 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
367 file, line, arg);
368 return 1;
369 }
370 return 0;
371}
372
373/* Report a warning if a rule is placed after a reqadd rule.
374 * Return 1 if the warning has been emitted, otherwise 0.
375 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100376int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200377{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100378 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200379 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
380 file, line, arg);
381 return 1;
382 }
383 return 0;
384}
385
386/* Report a warning if a rule is placed after a redirect rule.
387 * Return 1 if the warning has been emitted, otherwise 0.
388 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100389int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200390{
391 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
392 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
393 file, line, arg);
394 return 1;
395 }
396 return 0;
397}
398
399/* Report a warning if a rule is placed after a 'use_backend' rule.
400 * Return 1 if the warning has been emitted, otherwise 0.
401 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100402int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200403{
404 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
405 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
406 file, line, arg);
407 return 1;
408 }
409 return 0;
410}
411
Willy Tarreauee445d92014-04-23 01:39:04 +0200412/* Report a warning if a rule is placed after a 'use-server' rule.
413 * Return 1 if the warning has been emitted, otherwise 0.
414 */
415int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
416{
417 if (!LIST_ISEMPTY(&proxy->server_rules)) {
418 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
419 file, line, arg);
420 return 1;
421 }
422 return 0;
423}
424
Willy Tarreau8b3c8082014-09-16 15:39:51 +0200425/* report a warning if a "tcp request connection" rule is dangerously placed */
426int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
427{
428 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
429 warnif_rule_after_block(proxy, file, line, arg) ||
430 warnif_rule_after_http_req(proxy, file, line, arg) ||
431 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
432 warnif_rule_after_reqadd(proxy, file, line, arg) ||
433 warnif_rule_after_redirect(proxy, file, line, arg) ||
434 warnif_rule_after_use_backend(proxy, file, line, arg) ||
435 warnif_rule_after_use_server(proxy, file, line, arg);
436}
437
438/* report a warning if a "tcp request content" rule is dangerously placed */
439int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
440{
441 return warnif_rule_after_block(proxy, file, line, arg) ||
442 warnif_rule_after_http_req(proxy, file, line, arg) ||
443 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
444 warnif_rule_after_reqadd(proxy, file, line, arg) ||
445 warnif_rule_after_redirect(proxy, file, line, arg) ||
446 warnif_rule_after_use_backend(proxy, file, line, arg) ||
447 warnif_rule_after_use_server(proxy, file, line, arg);
448}
449
Willy Tarreau61d18892009-03-31 10:49:21 +0200450/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100451int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200452{
Willy Tarreau5002f572014-04-23 01:32:02 +0200453 return warnif_rule_after_http_req(proxy, file, line, arg) ||
454 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
455 warnif_rule_after_reqadd(proxy, file, line, arg) ||
456 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200457 warnif_rule_after_use_backend(proxy, file, line, arg) ||
458 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200459}
460
461/* report a warning if an http-request rule is dangerously placed */
462int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
463{
Willy Tarreau61d18892009-03-31 10:49:21 +0200464 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
465 warnif_rule_after_reqadd(proxy, file, line, arg) ||
466 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200467 warnif_rule_after_use_backend(proxy, file, line, arg) ||
468 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200469}
470
471/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100472int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200473{
474 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
475 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200476 warnif_rule_after_use_backend(proxy, file, line, arg) ||
477 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200478}
479
480/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100481int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200482{
483 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200484 warnif_rule_after_use_backend(proxy, file, line, arg) ||
485 warnif_rule_after_use_server(proxy, file, line, arg);
486}
487
488/* report a warning if a redirect rule is dangerously placed */
489int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
490{
491 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
492 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200493}
494
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100495/* Report it if a request ACL condition uses some keywords that are incompatible
496 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
497 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
498 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100499 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100500static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100501{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100502 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200503 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100504
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100505 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100506 return 0;
507
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100508 acl = acl_cond_conflicts(cond, where);
509 if (acl) {
510 if (acl->name && *acl->name)
511 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
512 file, line, acl->name, sample_ckp_names(where));
513 else
514 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200515 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100516 return ERR_WARN;
517 }
518 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100519 return 0;
520
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100521 if (acl->name && *acl->name)
522 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200523 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100524 else
525 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200526 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100527 return ERR_WARN;
528}
529
Willy Tarreaubaaee002006-06-26 02:48:02 +0200530/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200531 * parse a line in a <global> section. Returns the error code, 0 if OK, or
532 * any combination of :
533 * - ERR_ABORT: must abort ASAP
534 * - ERR_FATAL: we can continue parsing but not start the service
535 * - ERR_WARN: a warning has been emitted
536 * - ERR_ALERT: an alert has been emitted
537 * Only the two first ones can stop processing, the two others are just
538 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200539 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200540int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200541{
Willy Tarreau058e9072009-07-20 09:30:05 +0200542 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200543 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200544
545 if (!strcmp(args[0], "global")) { /* new section */
546 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200548 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200549 else if (!strcmp(args[0], "ca-base")) {
550#ifdef USE_OPENSSL
551 if (global.ca_base != NULL) {
552 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
553 err_code |= ERR_ALERT;
554 goto out;
555 }
556 if (*(args[1]) == 0) {
557 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
558 err_code |= ERR_ALERT | ERR_FATAL;
559 goto out;
560 }
561 global.ca_base = strdup(args[1]);
562#else
563 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
564 err_code |= ERR_ALERT | ERR_FATAL;
565 goto out;
566#endif
567 }
568 else if (!strcmp(args[0], "crt-base")) {
569#ifdef USE_OPENSSL
570 if (global.crt_base != NULL) {
571 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
572 err_code |= ERR_ALERT;
573 goto out;
574 }
575 if (*(args[1]) == 0) {
576 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
577 err_code |= ERR_ALERT | ERR_FATAL;
578 goto out;
579 }
580 global.crt_base = strdup(args[1]);
581#else
582 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
583 err_code |= ERR_ALERT | ERR_FATAL;
584 goto out;
585#endif
586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200587 else if (!strcmp(args[0], "daemon")) {
588 global.mode |= MODE_DAEMON;
589 }
590 else if (!strcmp(args[0], "debug")) {
591 global.mode |= MODE_DEBUG;
592 }
593 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100594 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200595 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200596 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100597 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200598 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200599 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100600 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200601 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100602 else if (!strcmp(args[0], "nosplice")) {
603 global.tune.options &= ~GTUNE_USE_SPLICE;
604 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200605 else if (!strcmp(args[0], "nogetaddrinfo")) {
606 global.tune.options &= ~GTUNE_USE_GAI;
607 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200608 else if (!strcmp(args[0], "quiet")) {
609 global.mode |= MODE_QUIET;
610 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200611 else if (!strcmp(args[0], "tune.maxpollevents")) {
612 if (global.tune.maxpollevents != 0) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 err_code |= ERR_ALERT;
615 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200621 }
622 global.tune.maxpollevents = atol(args[1]);
623 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100624 else if (!strcmp(args[0], "tune.maxaccept")) {
625 if (global.tune.maxaccept != 0) {
626 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200627 err_code |= ERR_ALERT;
628 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100629 }
630 if (*(args[1]) == 0) {
631 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200632 err_code |= ERR_ALERT | ERR_FATAL;
633 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100634 }
635 global.tune.maxaccept = atol(args[1]);
636 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200637 else if (!strcmp(args[0], "tune.chksize")) {
638 if (*(args[1]) == 0) {
639 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
640 err_code |= ERR_ALERT | ERR_FATAL;
641 goto out;
642 }
643 global.tune.chksize = atol(args[1]);
644 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200645#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200646 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
647 global.tune.sslprivatecache = 1;
648 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100649 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200650 if (*(args[1]) == 0) {
651 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
652 err_code |= ERR_ALERT | ERR_FATAL;
653 goto out;
654 }
655 global.tune.sslcachesize = atol(args[1]);
656 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100657 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
658 unsigned int ssllifetime;
659 const char *res;
660
661 if (*(args[1]) == 0) {
662 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
663 err_code |= ERR_ALERT | ERR_FATAL;
664 goto out;
665 }
666
667 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
668 if (res) {
669 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
670 file, linenum, *res, args[0]);
671 err_code |= ERR_ALERT | ERR_FATAL;
672 goto out;
673 }
674
675 global.tune.ssllifetime = ssllifetime;
676 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100677 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
678 if (*(args[1]) == 0) {
679 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
680 err_code |= ERR_ALERT | ERR_FATAL;
681 goto out;
682 }
683 global.tune.ssl_max_record = atol(args[1]);
684 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200685 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
686 if (*(args[1]) == 0) {
687 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
688 err_code |= ERR_ALERT | ERR_FATAL;
689 goto out;
690 }
691 global.tune.ssl_default_dh_param = atol(args[1]);
692 if (global.tune.ssl_default_dh_param < 1024) {
693 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
696 }
697 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200698#endif
Willy Tarreau27a674e2009-08-17 07:23:33 +0200699 else if (!strcmp(args[0], "tune.bufsize")) {
700 if (*(args[1]) == 0) {
701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
702 err_code |= ERR_ALERT | ERR_FATAL;
703 goto out;
704 }
705 global.tune.bufsize = atol(args[1]);
706 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
707 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100708 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100709 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200710 }
711 else if (!strcmp(args[0], "tune.maxrewrite")) {
712 if (*(args[1]) == 0) {
713 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
714 err_code |= ERR_ALERT | ERR_FATAL;
715 goto out;
716 }
717 global.tune.maxrewrite = atol(args[1]);
718 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
719 global.tune.maxrewrite = global.tune.bufsize / 2;
720 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100721 else if (!strcmp(args[0], "tune.idletimer")) {
722 unsigned int idle;
723 const char *res;
724
725 if (*(args[1]) == 0) {
726 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
727 err_code |= ERR_ALERT | ERR_FATAL;
728 goto out;
729 }
730
731 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
732 if (res) {
733 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
734 file, linenum, *res, args[0]);
735 err_code |= ERR_ALERT | ERR_FATAL;
736 goto out;
737 }
738
739 if (idle > 65535) {
740 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.idle_timer = idle;
745 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100746 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
747 if (global.tune.client_rcvbuf != 0) {
748 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
749 err_code |= ERR_ALERT;
750 goto out;
751 }
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757 global.tune.client_rcvbuf = atol(args[1]);
758 }
759 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
760 if (global.tune.server_rcvbuf != 0) {
761 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT;
763 goto out;
764 }
765 if (*(args[1]) == 0) {
766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
767 err_code |= ERR_ALERT | ERR_FATAL;
768 goto out;
769 }
770 global.tune.server_rcvbuf = atol(args[1]);
771 }
772 else if (!strcmp(args[0], "tune.sndbuf.client")) {
773 if (global.tune.client_sndbuf != 0) {
774 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
775 err_code |= ERR_ALERT;
776 goto out;
777 }
778 if (*(args[1]) == 0) {
779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
780 err_code |= ERR_ALERT | ERR_FATAL;
781 goto out;
782 }
783 global.tune.client_sndbuf = atol(args[1]);
784 }
785 else if (!strcmp(args[0], "tune.sndbuf.server")) {
786 if (global.tune.server_sndbuf != 0) {
787 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
788 err_code |= ERR_ALERT;
789 goto out;
790 }
791 if (*(args[1]) == 0) {
792 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
793 err_code |= ERR_ALERT | ERR_FATAL;
794 goto out;
795 }
796 global.tune.server_sndbuf = atol(args[1]);
797 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200798 else if (!strcmp(args[0], "tune.pipesize")) {
799 if (*(args[1]) == 0) {
800 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
801 err_code |= ERR_ALERT | ERR_FATAL;
802 goto out;
803 }
804 global.tune.pipesize = atol(args[1]);
805 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100806 else if (!strcmp(args[0], "tune.http.cookielen")) {
807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.cookie_len = atol(args[1]) + 1;
813 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200814 else if (!strcmp(args[0], "tune.http.maxhdr")) {
815 if (*(args[1]) == 0) {
816 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
817 err_code |= ERR_ALERT | ERR_FATAL;
818 goto out;
819 }
820 global.tune.max_http_hdr = atol(args[1]);
821 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100822 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
823#ifdef USE_ZLIB
824 if (*args[1]) {
825 global.tune.zlibmemlevel = atoi(args[1]);
826 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
827 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
828 file, linenum, args[0]);
829 err_code |= ERR_ALERT | ERR_FATAL;
830 goto out;
831 }
832 } else {
833 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
834 file, linenum, args[0]);
835 err_code |= ERR_ALERT | ERR_FATAL;
836 goto out;
837 }
838#else
839 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842#endif
843 }
844 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
845#ifdef USE_ZLIB
846 if (*args[1]) {
847 global.tune.zlibwindowsize = atoi(args[1]);
848 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
849 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
850 file, linenum, args[0]);
851 err_code |= ERR_ALERT | ERR_FATAL;
852 goto out;
853 }
854 } else {
855 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
856 file, linenum, args[0]);
857 err_code |= ERR_ALERT | ERR_FATAL;
858 goto out;
859 }
860#else
861 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864#endif
865 }
William Lallemandf3747832012-11-09 12:33:10 +0100866 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
867 if (*args[1]) {
868 global.tune.comp_maxlevel = atoi(args[1]);
869 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
870 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
871 file, linenum, args[0]);
872 err_code |= ERR_ALERT | ERR_FATAL;
873 goto out;
874 }
875 } else {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200882 else if (!strcmp(args[0], "uid")) {
883 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200884 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200885 err_code |= ERR_ALERT;
886 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200887 }
888 if (*(args[1]) == 0) {
889 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200890 err_code |= ERR_ALERT | ERR_FATAL;
891 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200892 }
893 global.uid = atol(args[1]);
894 }
895 else if (!strcmp(args[0], "gid")) {
896 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200897 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200898 err_code |= ERR_ALERT;
899 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200905 }
906 global.gid = atol(args[1]);
907 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200908 /* user/group name handling */
909 else if (!strcmp(args[0], "user")) {
910 struct passwd *ha_user;
911 if (global.uid != 0) {
912 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200913 err_code |= ERR_ALERT;
914 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200915 }
916 errno = 0;
917 ha_user = getpwnam(args[1]);
918 if (ha_user != NULL) {
919 global.uid = (int)ha_user->pw_uid;
920 }
921 else {
922 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200923 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200924 }
925 }
926 else if (!strcmp(args[0], "group")) {
927 struct group *ha_group;
928 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200929 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT;
931 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200932 }
933 errno = 0;
934 ha_group = getgrnam(args[1]);
935 if (ha_group != NULL) {
936 global.gid = (int)ha_group->gr_gid;
937 }
938 else {
939 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +0200940 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200941 }
942 }
943 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200944 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200945 if (*(args[1]) == 0) {
946 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200947 err_code |= ERR_ALERT | ERR_FATAL;
948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200949 }
950 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100951 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
952 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
953 file, linenum, args[0], LONGBITS, global.nbproc);
954 err_code |= ERR_ALERT | ERR_FATAL;
955 goto out;
956 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200957 }
958 else if (!strcmp(args[0], "maxconn")) {
959 if (global.maxconn != 0) {
960 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200961 err_code |= ERR_ALERT;
962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200963 }
964 if (*(args[1]) == 0) {
965 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200966 err_code |= ERR_ALERT | ERR_FATAL;
967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200968 }
969 global.maxconn = atol(args[1]);
970#ifdef SYSTEM_MAXCONN
971 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
972 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
973 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +0200974 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 }
976#endif /* SYSTEM_MAXCONN */
977 }
Willy Tarreau403edff2012-09-06 11:58:37 +0200978 else if (!strcmp(args[0], "maxsslconn")) {
979#ifdef USE_OPENSSL
980 if (*(args[1]) == 0) {
981 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
982 err_code |= ERR_ALERT | ERR_FATAL;
983 goto out;
984 }
985 global.maxsslconn = atol(args[1]);
986#else
Emeric Brun0914df82012-10-02 18:45:42 +0200987 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
988 err_code |= ERR_ALERT | ERR_FATAL;
989 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +0200990#endif
991 }
Willy Tarreau610f04b2014-02-13 11:36:41 +0100992 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
993#ifdef USE_OPENSSL
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999 free(global.listen_default_ciphers);
1000 global.listen_default_ciphers = strdup(args[1]);
1001#else
1002 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005#endif
1006 }
1007 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1008#ifdef USE_OPENSSL
1009 if (*(args[1]) == 0) {
1010 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1011 err_code |= ERR_ALERT | ERR_FATAL;
1012 goto out;
1013 }
1014 free(global.connect_default_ciphers);
1015 global.connect_default_ciphers = strdup(args[1]);
1016#else
1017 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
1020#endif
1021 }
Emeric Brun850efd52014-01-29 12:24:34 +01001022 else if (!strcmp(args[0], "ssl-server-verify")) {
1023 if (*(args[1]) == 0) {
1024 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 if (strcmp(args[1],"none") == 0)
1029 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1030 else if (strcmp(args[1],"required") == 0)
1031 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1032 else {
1033 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036 }
1037 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001038 else if (!strcmp(args[0], "maxconnrate")) {
1039 if (global.cps_lim != 0) {
1040 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT;
1042 goto out;
1043 }
1044 if (*(args[1]) == 0) {
1045 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1046 err_code |= ERR_ALERT | ERR_FATAL;
1047 goto out;
1048 }
1049 global.cps_lim = atol(args[1]);
1050 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001051 else if (!strcmp(args[0], "maxsessrate")) {
1052 if (global.sps_lim != 0) {
1053 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1054 err_code |= ERR_ALERT;
1055 goto out;
1056 }
1057 if (*(args[1]) == 0) {
1058 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1059 err_code |= ERR_ALERT | ERR_FATAL;
1060 goto out;
1061 }
1062 global.sps_lim = atol(args[1]);
1063 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001064 else if (!strcmp(args[0], "maxsslrate")) {
1065 if (global.ssl_lim != 0) {
1066 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1067 err_code |= ERR_ALERT;
1068 goto out;
1069 }
1070 if (*(args[1]) == 0) {
1071 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1072 err_code |= ERR_ALERT | ERR_FATAL;
1073 goto out;
1074 }
1075 global.ssl_lim = atol(args[1]);
1076 }
William Lallemandd85f9172012-11-09 17:05:39 +01001077 else if (!strcmp(args[0], "maxcomprate")) {
1078 if (*(args[1]) == 0) {
1079 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1080 err_code |= ERR_ALERT | ERR_FATAL;
1081 goto out;
1082 }
1083 global.comp_rate_lim = atoi(args[1]) * 1024;
1084 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001085 else if (!strcmp(args[0], "maxpipes")) {
1086 if (global.maxpipes != 0) {
1087 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT;
1089 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001090 }
1091 if (*(args[1]) == 0) {
1092 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001093 err_code |= ERR_ALERT | ERR_FATAL;
1094 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001095 }
1096 global.maxpipes = atol(args[1]);
1097 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001098 else if (!strcmp(args[0], "maxzlibmem")) {
1099 if (*(args[1]) == 0) {
1100 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1101 err_code |= ERR_ALERT | ERR_FATAL;
1102 goto out;
1103 }
William Lallemande3a7d992012-11-20 11:25:20 +01001104 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001105 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001106 else if (!strcmp(args[0], "maxcompcpuusage")) {
1107 if (*(args[1]) == 0) {
1108 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1109 err_code |= ERR_ALERT | ERR_FATAL;
1110 goto out;
1111 }
1112 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001113 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001114 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1115 err_code |= ERR_ALERT | ERR_FATAL;
1116 goto out;
1117 }
1118}
1119
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 else if (!strcmp(args[0], "ulimit-n")) {
1121 if (global.rlimit_nofile != 0) {
1122 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT;
1124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001125 }
1126 if (*(args[1]) == 0) {
1127 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001128 err_code |= ERR_ALERT | ERR_FATAL;
1129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001130 }
1131 global.rlimit_nofile = atol(args[1]);
1132 }
1133 else if (!strcmp(args[0], "chroot")) {
1134 if (global.chroot != NULL) {
1135 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001136 err_code |= ERR_ALERT;
1137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001138 }
1139 if (*(args[1]) == 0) {
1140 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT | ERR_FATAL;
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 global.chroot = strdup(args[1]);
1145 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001146 else if (!strcmp(args[0], "description")) {
1147 int i, len=0;
1148 char *d;
1149
1150 if (!*args[1]) {
1151 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1152 file, linenum, args[0]);
1153 err_code |= ERR_ALERT | ERR_FATAL;
1154 goto out;
1155 }
1156
Willy Tarreau348acfe2014-04-14 15:00:39 +02001157 for (i = 1; *args[i]; i++)
1158 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001159
1160 if (global.desc)
1161 free(global.desc);
1162
1163 global.desc = d = (char *)calloc(1, len);
1164
Willy Tarreau348acfe2014-04-14 15:00:39 +02001165 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1166 for (i = 2; *args[i]; i++)
1167 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001168 }
1169 else if (!strcmp(args[0], "node")) {
1170 int i;
1171 char c;
1172
1173 for (i=0; args[1][i]; i++) {
1174 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001175 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1176 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001177 break;
1178 }
1179
1180 if (!i || args[1][i]) {
1181 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1182 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1183 file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187
1188 if (global.node)
1189 free(global.node);
1190
1191 global.node = strdup(args[1]);
1192 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001193 else if (!strcmp(args[0], "pidfile")) {
1194 if (global.pidfile != NULL) {
1195 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001196 err_code |= ERR_ALERT;
1197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001198 }
1199 if (*(args[1]) == 0) {
1200 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT | ERR_FATAL;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 global.pidfile = strdup(args[1]);
1205 }
Emeric Bruned760922010-10-22 17:59:25 +02001206 else if (!strcmp(args[0], "unix-bind")) {
1207 int cur_arg = 1;
1208 while (*(args[cur_arg])) {
1209 if (!strcmp(args[cur_arg], "prefix")) {
1210 if (global.unix_bind.prefix != NULL) {
1211 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1212 err_code |= ERR_ALERT;
1213 cur_arg += 2;
1214 continue;
1215 }
1216
1217 if (*(args[cur_arg+1]) == 0) {
1218 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1223 cur_arg += 2;
1224 continue;
1225 }
1226
1227 if (!strcmp(args[cur_arg], "mode")) {
1228
1229 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1230 cur_arg += 2;
1231 continue;
1232 }
1233
1234 if (!strcmp(args[cur_arg], "uid")) {
1235
1236 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1237 cur_arg += 2;
1238 continue;
1239 }
1240
1241 if (!strcmp(args[cur_arg], "gid")) {
1242
1243 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1244 cur_arg += 2;
1245 continue;
1246 }
1247
1248 if (!strcmp(args[cur_arg], "user")) {
1249 struct passwd *user;
1250
1251 user = getpwnam(args[cur_arg + 1]);
1252 if (!user) {
1253 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1254 file, linenum, args[0], args[cur_arg + 1 ]);
1255 err_code |= ERR_ALERT | ERR_FATAL;
1256 goto out;
1257 }
1258
1259 global.unix_bind.ux.uid = user->pw_uid;
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (!strcmp(args[cur_arg], "group")) {
1265 struct group *group;
1266
1267 group = getgrnam(args[cur_arg + 1]);
1268 if (!group) {
1269 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1270 file, linenum, args[0], args[cur_arg + 1 ]);
1271 err_code |= ERR_ALERT | ERR_FATAL;
1272 goto out;
1273 }
1274
1275 global.unix_bind.ux.gid = group->gr_gid;
1276 cur_arg += 2;
1277 continue;
1278 }
1279
Willy Tarreaub48f9582011-09-05 01:17:06 +02001280 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001281 file, linenum, args[0]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285 }
William Lallemand0f99e342011-10-12 17:50:54 +02001286 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1287 /* delete previous herited or defined syslog servers */
1288 struct logsrv *back;
1289 struct logsrv *tmp;
1290
1291 if (*(args[1]) != 0) {
1292 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
1296
1297 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1298 LIST_DEL(&tmp->list);
1299 free(tmp);
1300 }
1301 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001302 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001303 struct sockaddr_storage *sk;
1304 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001305 struct logsrv *logsrv;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001306 int arg = 0;
1307 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001308
Willy Tarreaubaaee002006-06-26 02:48:02 +02001309 if (*(args[1]) == 0 || *(args[2]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001313 }
William Lallemand0f99e342011-10-12 17:50:54 +02001314
1315 logsrv = calloc(1, sizeof(struct logsrv));
1316
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001317 /* just after the address, a length may be specified */
1318 if (strcmp(args[arg+2], "len") == 0) {
1319 len = atoi(args[arg+3]);
1320 if (len < 80 || len > 65535) {
1321 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1322 file, linenum, args[arg+3]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326 logsrv->maxlen = len;
1327
1328 /* skip these two args */
1329 arg += 2;
1330 }
1331 else
1332 logsrv->maxlen = MAX_SYSLOG_LEN;
1333
1334 if (logsrv->maxlen > global.max_syslog_len) {
1335 global.max_syslog_len = logsrv->maxlen;
1336 logline = realloc(logline, global.max_syslog_len + 1);
1337 }
1338
1339 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001340 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001341 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001342 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001343 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001344 }
1345
William Lallemand0f99e342011-10-12 17:50:54 +02001346 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001347 if (*(args[arg+3])) {
1348 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001349 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001350 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001351 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001352 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001353 }
1354 }
1355
William Lallemand0f99e342011-10-12 17:50:54 +02001356 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001357 if (*(args[arg+4])) {
1358 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001359 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02001360 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001361 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001362 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001363 }
1364 }
1365
Willy Tarreau902636f2013-03-10 19:44:48 +01001366 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001367 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001368 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001369 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001370 free(logsrv);
1371 goto out;
1372 }
1373 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001374
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001375 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001376 if (port1 != port2) {
1377 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1378 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001379 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001380 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001381 goto out;
1382 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001383
William Lallemand0f99e342011-10-12 17:50:54 +02001384 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001385 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001386 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001388
William Lallemand0f99e342011-10-12 17:50:54 +02001389 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001390 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001391 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1392 char *name;
1393 int len;
1394
1395 if (global.log_send_hostname != NULL) {
1396 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1397 err_code |= ERR_ALERT;
1398 goto out;
1399 }
1400
1401 if (*(args[1]))
1402 name = args[1];
1403 else
1404 name = hostname;
1405
1406 len = strlen(name);
1407
1408 /* We'll add a space after the name to respect the log format */
1409 free(global.log_send_hostname);
1410 global.log_send_hostname = malloc(len + 2);
1411 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1412 }
Kevinm48936af2010-12-22 16:08:21 +00001413 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1414 if (*(args[1]) == 0) {
1415 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1416 err_code |= ERR_ALERT | ERR_FATAL;
1417 goto out;
1418 }
1419 free(global.log_tag);
1420 global.log_tag = strdup(args[1]);
1421 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001422 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1423 if (global.spread_checks != 0) {
1424 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001425 err_code |= ERR_ALERT;
1426 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001427 }
1428 if (*(args[1]) == 0) {
1429 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001430 err_code |= ERR_ALERT | ERR_FATAL;
1431 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001432 }
1433 global.spread_checks = atol(args[1]);
1434 if (global.spread_checks < 0 || global.spread_checks > 50) {
1435 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001436 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001439 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1440 const char *err;
1441 unsigned int val;
1442
1443
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449
1450 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1451 if (err) {
1452 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1453 err_code |= ERR_ALERT | ERR_FATAL;
1454 }
1455 global.max_spread_checks = val;
1456 if (global.max_spread_checks < 0) {
1457 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1458 err_code |= ERR_ALERT | ERR_FATAL;
1459 }
1460 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001461 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1462#ifdef USE_CPU_AFFINITY
1463 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001464 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001465 unsigned long cpus = 0;
1466
1467 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001468 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001469 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001470 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001471 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001472 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001473 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001474 proc = atol(args[1]);
1475 if (proc >= 1 && proc <= LONGBITS)
1476 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001477 }
1478
1479 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001480 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1481 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 cur_arg = 2;
1487 while (*args[cur_arg]) {
1488 unsigned int low, high;
1489
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001490 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001491 char *dash = strchr(args[cur_arg], '-');
1492
1493 low = high = str2uic(args[cur_arg]);
1494 if (dash)
1495 high = str2uic(dash + 1);
1496
1497 if (high < low) {
1498 unsigned int swap = low;
1499 low = high;
1500 high = swap;
1501 }
1502
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001503 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001504 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001505 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509
1510 while (low <= high)
1511 cpus |= 1UL << low++;
1512 }
1513 else {
1514 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1515 file, linenum, args[0], args[cur_arg]);
1516 err_code |= ERR_ALERT | ERR_FATAL;
1517 goto out;
1518 }
1519 cur_arg++;
1520 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001521 for (i = 0; i < LONGBITS; i++)
1522 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001523 global.cpu_map[i] = cpus;
1524#else
1525 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1526 err_code |= ERR_ALERT | ERR_FATAL;
1527 goto out;
1528#endif
1529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001531 struct cfg_kw_list *kwl;
1532 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001533 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001534
1535 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1536 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1537 if (kwl->kw[index].section != CFG_GLOBAL)
1538 continue;
1539 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001540 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001541 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001542 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001543 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001544 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001545 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001546 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001547 err_code |= ERR_WARN;
1548 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001549 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001550 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001551 }
1552 }
1553 }
1554
Willy Tarreaubaaee002006-06-26 02:48:02 +02001555 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001556 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001557 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001558
Willy Tarreau058e9072009-07-20 09:30:05 +02001559 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001560 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001562}
1563
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001564void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001565{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001566 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001567 defproxy.mode = PR_MODE_TCP;
1568 defproxy.state = PR_STNEW;
1569 defproxy.maxconn = cfg_maxpconn;
1570 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001571
Simon Horman66183002013-02-23 10:16:43 +09001572 defproxy.defsrv.check.inter = DEF_CHKINTR;
1573 defproxy.defsrv.check.fastinter = 0;
1574 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001575 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1576 defproxy.defsrv.agent.fastinter = 0;
1577 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001578 defproxy.defsrv.check.rise = DEF_RISETIME;
1579 defproxy.defsrv.check.fall = DEF_FALLTIME;
1580 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1581 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001582 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001583 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001584 defproxy.defsrv.maxqueue = 0;
1585 defproxy.defsrv.minconn = 0;
1586 defproxy.defsrv.maxconn = 0;
1587 defproxy.defsrv.slowstart = 0;
1588 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1589 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1590 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001591}
1592
Willy Tarreauade5ec42010-01-28 19:33:49 +01001593
Willy Tarreau63af98d2014-05-18 08:11:41 +02001594/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1595 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1596 * ERR_FATAL in case of error.
1597 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001598static int create_cond_regex_rule(const char *file, int line,
1599 struct proxy *px, int dir, int action, int flags,
1600 const char *cmd, const char *reg, const char *repl,
1601 const char **cond_start)
1602{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001603 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001604 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001605 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001606 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001607 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001608 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001609 int cs;
1610 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001611
1612 if (px == &defproxy) {
1613 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001614 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001615 goto err;
1616 }
1617
1618 if (*reg == 0) {
1619 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001620 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001621 goto err;
1622 }
1623
1624 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001625 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001626
Willy Tarreau5321c422010-01-28 20:35:13 +01001627 if (cond_start &&
1628 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001629 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1630 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1631 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001632 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001633 goto err;
1634 }
1635 }
1636 else if (cond_start && **cond_start) {
1637 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1638 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001639 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001640 goto err;
1641 }
1642
Willy Tarreau63af98d2014-05-18 08:11:41 +02001643 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001644 (dir == SMP_OPT_DIR_REQ) ?
1645 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1646 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1647 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001648
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001649 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001650 if (!preg) {
1651 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001652 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001653 goto err;
1654 }
1655
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001656 cs = !(flags & REG_ICASE);
1657 cap = !(flags & REG_NOSUB);
1658 error = NULL;
1659 if (!regex_comp(reg, preg, cs, cap, &error)) {
1660 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1661 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001662 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001663 goto err;
1664 }
1665
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001666 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001667 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001668 if (repl && err) {
1669 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1670 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
1672 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001673 }
1674
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001675 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001676 ret_code |= ERR_WARN;
1677
1678 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001679
Willy Tarreau63af98d2014-05-18 08:11:41 +02001680 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001681 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682 err:
1683 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001684 free(errmsg);
1685 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001686}
1687
Willy Tarreaubaaee002006-06-26 02:48:02 +02001688/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001689 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001690 * Returns the error code, 0 if OK, or any combination of :
1691 * - ERR_ABORT: must abort ASAP
1692 * - ERR_FATAL: we can continue parsing but not start the service
1693 * - ERR_WARN: a warning has been emitted
1694 * - ERR_ALERT: an alert has been emitted
1695 * Only the two first ones can stop processing, the two others are just
1696 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001697 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001698int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1699{
1700 static struct peers *curpeers = NULL;
1701 struct peer *newpeer = NULL;
1702 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001703 struct bind_conf *bind_conf;
1704 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001705 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001706 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001707
1708 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001709 if (!*args[1]) {
1710 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001711 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001712 goto out;
1713 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001714
1715 err = invalid_char(args[1]);
1716 if (err) {
1717 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1718 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001719 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001720 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001721 }
1722
1723 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1724 /*
1725 * If there are two proxies with the same name only following
1726 * combinations are allowed:
1727 */
1728 if (strcmp(curpeers->id, args[1]) == 0) {
1729 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1730 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1731 err_code |= ERR_WARN;
1732 }
1733 }
1734
1735 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1736 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1737 err_code |= ERR_ALERT | ERR_ABORT;
1738 goto out;
1739 }
1740
1741 curpeers->next = peers;
1742 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001743 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001744 curpeers->conf.line = linenum;
1745 curpeers->last_change = now.tv_sec;
1746 curpeers->id = strdup(args[1]);
1747 }
1748 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001749 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001750 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001751 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001752
1753 if (!*args[2]) {
1754 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1755 file, linenum, args[0]);
1756 err_code |= ERR_ALERT | ERR_FATAL;
1757 goto out;
1758 }
1759
1760 err = invalid_char(args[1]);
1761 if (err) {
1762 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1763 file, linenum, *err, args[1]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766 }
1767
1768 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1769 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1770 err_code |= ERR_ALERT | ERR_ABORT;
1771 goto out;
1772 }
1773
1774 /* the peers are linked backwards first */
1775 curpeers->count++;
1776 newpeer->next = curpeers->remote;
1777 curpeers->remote = newpeer;
1778 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001779 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001780 newpeer->conf.line = linenum;
1781
1782 newpeer->last_change = now.tv_sec;
1783 newpeer->id = strdup(args[1]);
1784
Willy Tarreau902636f2013-03-10 19:44:48 +01001785 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001786 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001787 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001790 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001791
1792 proto = protocol_by_family(sk->ss_family);
1793 if (!proto || !proto->connect) {
1794 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1795 file, linenum, args[0], args[1]);
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
1798 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001799
1800 if (port1 != port2) {
1801 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1802 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001803 err_code |= ERR_ALERT | ERR_FATAL;
1804 goto out;
1805 }
1806
Willy Tarreau2aa38802013-02-20 19:20:59 +01001807 if (!port1) {
1808 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1809 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001810 err_code |= ERR_ALERT | ERR_FATAL;
1811 goto out;
1812 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001813
Emeric Brun32da3c42010-09-23 18:39:19 +02001814 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001815 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001816 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001817 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001818
Emeric Brun32da3c42010-09-23 18:39:19 +02001819 if (strcmp(newpeer->id, localpeer) == 0) {
1820 /* Current is local peer, it define a frontend */
1821 newpeer->local = 1;
1822
1823 if (!curpeers->peers_fe) {
1824 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1825 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1826 err_code |= ERR_ALERT | ERR_ABORT;
1827 goto out;
1828 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001829
Willy Tarreau237250c2011-07-29 01:49:03 +02001830 init_new_proxy(curpeers->peers_fe);
1831 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001832
1833 curpeers->peers_fe->last_change = now.tv_sec;
1834 curpeers->peers_fe->id = strdup(args[1]);
1835 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001836 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001837 curpeers->peers_fe->conn_retries = CONN_RETRIES;
Willy Tarreaufc940eb2015-03-13 16:18:25 +01001838 curpeers->peers_fe->timeout.client = MS_TO_TICKS(5000);
Emeric Brun32da3c42010-09-23 18:39:19 +02001839 curpeers->peers_fe->accept = peer_accept;
1840 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001841 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1842 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001843
1844 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1845
Willy Tarreau902636f2013-03-10 19:44:48 +01001846 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1847 if (errmsg && *errmsg) {
1848 indent_msg(&errmsg, 2);
1849 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001850 }
1851 else
1852 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1853 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001854 err_code |= ERR_FATAL;
1855 goto out;
1856 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001857
1858 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001859 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001860 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1861 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1862 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1863 l->accept = session_accept;
1864 l->handler = process_session;
1865 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1866 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1867 global.maxsock += l->maxconn;
1868 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001869 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001870 else {
1871 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1872 file, linenum, args[0], args[1],
1873 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1874 err_code |= ERR_FATAL;
1875 goto out;
1876 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001877 }
1878 } /* neither "peer" nor "peers" */
1879 else if (*args[0] != 0) {
1880 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1881 err_code |= ERR_ALERT | ERR_FATAL;
1882 goto out;
1883 }
1884
1885out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001886 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001887 return err_code;
1888}
1889
Willy Tarreau3842f002009-06-14 11:39:52 +02001890int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02001891{
1892 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02001893 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001894 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01001895 int rc;
1896 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02001897 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01001898 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01001899 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02001900 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02001901 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001902
Willy Tarreau977b8e42006-12-29 14:19:17 +01001903 if (!strcmp(args[0], "listen"))
1904 rc = PR_CAP_LISTEN;
1905 else if (!strcmp(args[0], "frontend"))
1906 rc = PR_CAP_FE | PR_CAP_RS;
1907 else if (!strcmp(args[0], "backend"))
1908 rc = PR_CAP_BE | PR_CAP_RS;
1909 else if (!strcmp(args[0], "ruleset"))
1910 rc = PR_CAP_RS;
1911 else
1912 rc = PR_CAP_NONE;
1913
1914 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001915 struct ebpt_node *node;
1916
Willy Tarreaubaaee002006-06-26 02:48:02 +02001917 if (!*args[1]) {
1918 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
1919 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
1920 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02001921 err_code |= ERR_ALERT | ERR_ABORT;
1922 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001923 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001924
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001925 err = invalid_char(args[1]);
1926 if (err) {
1927 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1928 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02001929 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01001930 }
1931
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001932 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
1933 curproxy = container_of(node, struct proxy, conf.by_name);
1934
1935 if (strcmp(curproxy->id, args[1]) != 0)
1936 break;
1937
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001938 /*
1939 * If there are two proxies with the same name only following
1940 * combinations are allowed:
1941 *
1942 * listen backend frontend ruleset
1943 * listen - - - -
1944 * backend - - OK -
1945 * frontend - OK - -
1946 * ruleset - - - -
1947 */
1948
Willy Tarreau7cbc9152014-03-15 08:17:08 +01001949 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
1950 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02001951 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
1952 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
1953 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02001954 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02001955 }
1956 }
1957
Willy Tarreaubaaee002006-06-26 02:48:02 +02001958 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
1959 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02001960 err_code |= ERR_ALERT | ERR_ABORT;
1961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001962 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01001963
Willy Tarreau97cb7802010-01-03 20:23:58 +01001964 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001965 curproxy->next = proxy;
1966 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001967 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
1968 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02001969 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001970 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01001971 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01001972 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001973
1974 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01001975 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02001976 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02001977
Willy Tarreau4348fad2012-09-20 16:48:07 +02001978 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
1979
Willy Tarreau902636f2013-03-10 19:44:48 +01001980 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
1981 if (errmsg && *errmsg) {
1982 indent_msg(&errmsg, 2);
1983 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001984 }
1985 else
1986 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
1987 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02001988 err_code |= ERR_FATAL;
1989 goto out;
1990 }
Willy Tarreau81a81172012-09-18 20:52:35 +02001991
Willy Tarreau4348fad2012-09-20 16:48:07 +02001992 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01001993 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02001994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001995 }
1996
1997 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001998 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02001999 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002000
Willy Tarreaubaaee002006-06-26 02:48:02 +02002001 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002002 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002003 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002004 curproxy->no_options = defproxy.no_options;
2005 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002006 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002007 curproxy->except_net = defproxy.except_net;
2008 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002009 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002010 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002011
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002012 if (defproxy.fwdfor_hdr_len) {
2013 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2014 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2015 }
2016
Willy Tarreaub86db342009-11-30 11:50:16 +01002017 if (defproxy.orgto_hdr_len) {
2018 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2019 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2020 }
2021
Mark Lamourinec2247f02012-01-04 13:02:01 -05002022 if (defproxy.server_id_hdr_len) {
2023 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2024 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2025 }
2026
Willy Tarreau977b8e42006-12-29 14:19:17 +01002027 if (curproxy->cap & PR_CAP_FE) {
2028 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002029 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002030 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002031
2032 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002033 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2034 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002035
2036 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002038
Willy Tarreau977b8e42006-12-29 14:19:17 +01002039 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaucac307c2014-11-18 15:04:29 +01002040 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002041 curproxy->fullconn = defproxy.fullconn;
2042 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002043 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002044
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002045 if (defproxy.check_req) {
2046 curproxy->check_req = calloc(1, defproxy.check_len);
2047 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2048 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002049 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002050
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002051 if (defproxy.expect_str) {
2052 curproxy->expect_str = strdup(defproxy.expect_str);
2053 if (defproxy.expect_regex) {
2054 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002055 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2056 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002057 }
2058 }
2059
Willy Tarreau67402132012-05-31 20:40:20 +02002060 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002061 if (defproxy.cookie_name)
2062 curproxy->cookie_name = strdup(defproxy.cookie_name);
2063 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002064 if (defproxy.cookie_domain)
2065 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002066
Willy Tarreau31936852010-10-06 16:59:56 +02002067 if (defproxy.cookie_maxidle)
2068 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2069
2070 if (defproxy.cookie_maxlife)
2071 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2072
Emeric Brun647caf12009-06-30 17:57:00 +02002073 if (defproxy.rdp_cookie_name)
2074 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2075 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2076
Willy Tarreau01732802007-11-01 22:48:15 +01002077 if (defproxy.url_param_name)
2078 curproxy->url_param_name = strdup(defproxy.url_param_name);
2079 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002080
Benoitaffb4812009-03-25 13:02:10 +01002081 if (defproxy.hh_name)
2082 curproxy->hh_name = strdup(defproxy.hh_name);
2083 curproxy->hh_len = defproxy.hh_len;
2084 curproxy->hh_match_domain = defproxy.hh_match_domain;
2085
Willy Tarreauef9a3602012-12-08 22:29:20 +01002086 if (defproxy.conn_src.iface_name)
2087 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2088 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002089 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002090#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002091 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002092#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002093 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002094
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002095 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002096 if (defproxy.capture_name)
2097 curproxy->capture_name = strdup(defproxy.capture_name);
2098 curproxy->capture_namelen = defproxy.capture_namelen;
2099 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002101
Willy Tarreau977b8e42006-12-29 14:19:17 +01002102 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002103 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002104 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002105 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002106 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002107 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002108 curproxy->mon_net = defproxy.mon_net;
2109 curproxy->mon_mask = defproxy.mon_mask;
2110 if (defproxy.monitor_uri)
2111 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2112 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002113 if (defproxy.defbe.name)
2114 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002115
2116 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002117 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2118 if (curproxy->conf.logformat_string &&
2119 curproxy->conf.logformat_string != default_http_log_format &&
2120 curproxy->conf.logformat_string != default_tcp_log_format &&
2121 curproxy->conf.logformat_string != clf_http_log_format)
2122 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2123
2124 if (defproxy.conf.lfs_file) {
2125 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2126 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2127 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002128 }
2129
2130 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002131 curproxy->timeout.connect = defproxy.timeout.connect;
2132 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002133 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002134 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002135 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002136 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002137 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002138 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002139 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002140 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002141 }
2142
Willy Tarreaubaaee002006-06-26 02:48:02 +02002143 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002144 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002145
2146 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002147 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002148 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002149 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002150 LIST_INIT(&node->list);
2151 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2152 }
2153
Willy Tarreau62a61232013-04-12 18:13:46 +02002154 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2155 if (curproxy->conf.uniqueid_format_string)
2156 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2157
2158 if (defproxy.conf.uif_file) {
2159 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2160 curproxy->conf.uif_line = defproxy.conf.uif_line;
2161 }
William Lallemanda73203e2012-03-12 12:48:57 +01002162
2163 /* copy default header unique id */
2164 if (defproxy.header_unique_id)
2165 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2166
William Lallemand82fe75c2012-10-23 10:25:10 +02002167 /* default compression options */
2168 if (defproxy.comp != NULL) {
2169 curproxy->comp = calloc(1, sizeof(struct comp));
2170 curproxy->comp->algos = defproxy.comp->algos;
2171 curproxy->comp->types = defproxy.comp->types;
2172 }
2173
Willy Tarreaubaaee002006-06-26 02:48:02 +02002174 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002175 curproxy->conf.used_listener_id = EB_ROOT;
2176 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002177
Willy Tarreau93893792009-07-23 13:19:11 +02002178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002179 }
2180 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2181 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002182 /* FIXME-20070101: we should do this too at the end of the
2183 * config parsing to free all default values.
2184 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002185 free(defproxy.check_req);
2186 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002187 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002188 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002189 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002190 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002191 free(defproxy.capture_name);
2192 free(defproxy.monitor_uri);
2193 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002194 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002195 free(defproxy.fwdfor_hdr_name);
2196 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002197 free(defproxy.orgto_hdr_name);
2198 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002199 free(defproxy.server_id_hdr_name);
2200 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002201 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002202 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002203 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002204 free(defproxy.expect_regex);
2205 defproxy.expect_regex = NULL;
2206 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002207
Willy Tarreau62a61232013-04-12 18:13:46 +02002208 if (defproxy.conf.logformat_string != default_http_log_format &&
2209 defproxy.conf.logformat_string != default_tcp_log_format &&
2210 defproxy.conf.logformat_string != clf_http_log_format)
2211 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002212
Willy Tarreau62a61232013-04-12 18:13:46 +02002213 free(defproxy.conf.uniqueid_format_string);
2214 free(defproxy.conf.lfs_file);
2215 free(defproxy.conf.uif_file);
Willy Tarreau196729e2012-05-31 19:30:26 +02002216
Willy Tarreaua534fea2008-08-03 12:19:50 +02002217 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002218 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002219
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220 /* we cannot free uri_auth because it might already be used */
2221 init_default_instance();
2222 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002223 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2224 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002226 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227 }
2228 else if (curproxy == NULL) {
2229 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002230 err_code |= ERR_ALERT | ERR_FATAL;
2231 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002232 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002233
2234 /* update the current file and line being parsed */
2235 curproxy->conf.args.file = curproxy->conf.file;
2236 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237
2238 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002239 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2240 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2241 if (err_code & ERR_FATAL)
2242 goto out;
2243 }
2244 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002245 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002246 int cur_arg;
2247
Willy Tarreaubaaee002006-06-26 02:48:02 +02002248 if (curproxy == &defproxy) {
2249 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002252 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002253 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002254 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002255
Willy Tarreau24709282013-03-10 21:32:12 +01002256 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002257 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002258 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002261 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002262
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002263 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002264
2265 /* use default settings for unix sockets */
2266 bind_conf->ux.uid = global.unix_bind.ux.uid;
2267 bind_conf->ux.gid = global.unix_bind.ux.gid;
2268 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002269
2270 /* NOTE: the following line might create several listeners if there
2271 * are comma-separated IPs or port ranges. So all further processing
2272 * will have to be applied to all listeners created after last_listen.
2273 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002274 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2275 if (errmsg && *errmsg) {
2276 indent_msg(&errmsg, 2);
2277 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002278 }
2279 else
2280 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2281 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002282 err_code |= ERR_ALERT | ERR_FATAL;
2283 goto out;
2284 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002285
Willy Tarreau4348fad2012-09-20 16:48:07 +02002286 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2287 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002288 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002289 }
2290
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002291 cur_arg = 2;
2292 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002293 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002294 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002295 char *err;
2296
Willy Tarreau26982662012-09-12 23:17:10 +02002297 kw = bind_find_kw(args[cur_arg]);
2298 if (kw) {
2299 char *err = NULL;
2300 int code;
2301
2302 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002303 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2304 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002305 cur_arg += 1 + kw->skip ;
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
Willy Tarreau4348fad2012-09-20 16:48:07 +02002310 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002311 err_code |= code;
2312
2313 if (code) {
2314 if (err && *err) {
2315 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002316 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002317 }
2318 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002319 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2320 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002321 if (code & ERR_FATAL) {
2322 free(err);
2323 cur_arg += 1 + kw->skip;
2324 goto out;
2325 }
2326 }
2327 free(err);
2328 cur_arg += 1 + kw->skip;
2329 continue;
2330 }
2331
Willy Tarreau8638f482012-09-18 18:01:17 +02002332 err = NULL;
2333 if (!bind_dumped) {
2334 bind_dump_kws(&err);
2335 indent_msg(&err, 4);
2336 bind_dumped = 1;
2337 }
2338
2339 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2340 file, linenum, args[0], args[1], args[cur_arg],
2341 err ? " Registered keywords :" : "", err ? err : "");
2342 free(err);
2343
Willy Tarreau93893792009-07-23 13:19:11 +02002344 err_code |= ERR_ALERT | ERR_FATAL;
2345 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002346 }
Willy Tarreau93893792009-07-23 13:19:11 +02002347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002348 }
2349 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002350 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002351 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2352 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002353 err_code |= ERR_ALERT | ERR_FATAL;
2354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002355 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002356 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002357 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002358
Willy Tarreaubaaee002006-06-26 02:48:02 +02002359 /* flush useless bits */
2360 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002362 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002363 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002364 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002365 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002366
Willy Tarreau1c47f852006-07-09 08:22:27 +02002367 if (!*args[1]) {
2368 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2369 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
2371 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002372 }
2373
Willy Tarreaua534fea2008-08-03 12:19:50 +02002374 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002375 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002376 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002377 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002378 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2379
Willy Tarreau93893792009-07-23 13:19:11 +02002380 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002382 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2383 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2384 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2385 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2386 else {
2387 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002388 err_code |= ERR_ALERT | ERR_FATAL;
2389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002390 }
2391 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002392 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002393 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002394
2395 if (curproxy == &defproxy) {
2396 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2397 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002398 err_code |= ERR_ALERT | ERR_FATAL;
2399 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002400 }
2401
2402 if (!*args[1]) {
2403 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2404 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002405 err_code |= ERR_ALERT | ERR_FATAL;
2406 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002407 }
2408
2409 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002410 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002411
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002412 if (curproxy->uuid <= 0) {
2413 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002414 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002415 err_code |= ERR_ALERT | ERR_FATAL;
2416 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002417 }
2418
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002419 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2420 if (node) {
2421 struct proxy *target = container_of(node, struct proxy, conf.id);
2422 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2423 file, linenum, proxy_type_str(curproxy), curproxy->id,
2424 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
2427 }
2428 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002429 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002430 else if (!strcmp(args[0], "description")) {
2431 int i, len=0;
2432 char *d;
2433
Cyril Bonté99ed3272010-01-24 23:29:44 +01002434 if (curproxy == &defproxy) {
2435 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2436 file, linenum, args[0]);
2437 err_code |= ERR_ALERT | ERR_FATAL;
2438 goto out;
2439 }
2440
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002441 if (!*args[1]) {
2442 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2443 file, linenum, args[0]);
2444 return -1;
2445 }
2446
Willy Tarreau348acfe2014-04-14 15:00:39 +02002447 for (i = 1; *args[i]; i++)
2448 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002449
2450 d = (char *)calloc(1, len);
2451 curproxy->desc = d;
2452
Willy Tarreau348acfe2014-04-14 15:00:39 +02002453 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2454 for (i = 2; *args[i]; i++)
2455 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002456
2457 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2459 curproxy->state = PR_STSTOPPED;
2460 }
2461 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2462 curproxy->state = PR_STNEW;
2463 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002464 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2465 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002466 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002467
2468 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002469 unsigned int low, high;
2470
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002471 if (strcmp(args[cur_arg], "all") == 0) {
2472 set = 0;
2473 break;
2474 }
2475 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002476 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002477 }
2478 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002479 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002480 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002481 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002482 char *dash = strchr(args[cur_arg], '-');
2483
2484 low = high = str2uic(args[cur_arg]);
2485 if (dash)
2486 high = str2uic(dash + 1);
2487
2488 if (high < low) {
2489 unsigned int swap = low;
2490 low = high;
2491 high = swap;
2492 }
2493
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002494 if (low < 1 || high > LONGBITS) {
2495 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2496 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002497 err_code |= ERR_ALERT | ERR_FATAL;
2498 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002499 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002500 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002501 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002502 }
2503 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002504 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2505 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002506 err_code |= ERR_ALERT | ERR_FATAL;
2507 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002508 }
2509 cur_arg++;
2510 }
2511 curproxy->bind_proc = set;
2512 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002513 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002514 if (curproxy == &defproxy) {
2515 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002516 err_code |= ERR_ALERT | ERR_FATAL;
2517 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002518 }
2519
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002520 err = invalid_char(args[1]);
2521 if (err) {
2522 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2523 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002524 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002525 }
2526
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002527 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002528 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2529 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002530 err_code |= ERR_ALERT | ERR_FATAL;
2531 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002532 }
2533 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002534 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2535 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536
Willy Tarreau977b8e42006-12-29 14:19:17 +01002537 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002538 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002539
Willy Tarreaubaaee002006-06-26 02:48:02 +02002540 if (*(args[1]) == 0) {
2541 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2542 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002546
Willy Tarreau67402132012-05-31 20:40:20 +02002547 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002548 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002549 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002550 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002551 curproxy->cookie_name = strdup(args[1]);
2552 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002553
Willy Tarreaubaaee002006-06-26 02:48:02 +02002554 cur_arg = 2;
2555 while (*(args[cur_arg])) {
2556 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002557 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002558 }
2559 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002560 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002561 }
2562 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002563 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 }
2565 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002566 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
2568 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002569 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002570 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002571 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002572 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002573 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002575 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002577 else if (!strcmp(args[cur_arg], "httponly")) {
2578 curproxy->ck_opts |= PR_CK_HTTPONLY;
2579 }
2580 else if (!strcmp(args[cur_arg], "secure")) {
2581 curproxy->ck_opts |= PR_CK_SECURE;
2582 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002583 else if (!strcmp(args[cur_arg], "domain")) {
2584 if (!*args[cur_arg + 1]) {
2585 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2586 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002587 err_code |= ERR_ALERT | ERR_FATAL;
2588 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002589 }
2590
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002591 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002592 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002593 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2594 " dots nor does not start with a dot."
2595 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002596 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002597 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002598 }
2599
2600 err = invalid_domainchar(args[cur_arg + 1]);
2601 if (err) {
2602 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2603 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002604 err_code |= ERR_ALERT | ERR_FATAL;
2605 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002606 }
2607
Willy Tarreau68a897b2009-12-03 23:28:34 +01002608 if (!curproxy->cookie_domain) {
2609 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2610 } else {
2611 /* one domain was already specified, add another one by
2612 * building the string which will be returned along with
2613 * the cookie.
2614 */
2615 char *new_ptr;
2616 int new_len = strlen(curproxy->cookie_domain) +
2617 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2618 new_ptr = malloc(new_len);
2619 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2620 free(curproxy->cookie_domain);
2621 curproxy->cookie_domain = new_ptr;
2622 }
Willy Tarreau31936852010-10-06 16:59:56 +02002623 cur_arg++;
2624 }
2625 else if (!strcmp(args[cur_arg], "maxidle")) {
2626 unsigned int maxidle;
2627 const char *res;
2628
2629 if (!*args[cur_arg + 1]) {
2630 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2631 file, linenum, args[cur_arg]);
2632 err_code |= ERR_ALERT | ERR_FATAL;
2633 goto out;
2634 }
2635
2636 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2637 if (res) {
2638 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2639 file, linenum, *res, args[cur_arg]);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643 curproxy->cookie_maxidle = maxidle;
2644 cur_arg++;
2645 }
2646 else if (!strcmp(args[cur_arg], "maxlife")) {
2647 unsigned int maxlife;
2648 const char *res;
2649
2650 if (!*args[cur_arg + 1]) {
2651 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2652 file, linenum, args[cur_arg]);
2653 err_code |= ERR_ALERT | ERR_FATAL;
2654 goto out;
2655 }
2656
2657 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2658 if (res) {
2659 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2660 file, linenum, *res, args[cur_arg]);
2661 err_code |= ERR_ALERT | ERR_FATAL;
2662 goto out;
2663 }
2664 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002665 cur_arg++;
2666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002667 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002668 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 +02002669 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002670 err_code |= ERR_ALERT | ERR_FATAL;
2671 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002672 }
2673 cur_arg++;
2674 }
Willy Tarreau67402132012-05-31 20:40:20 +02002675 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002676 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2677 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002678 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679 }
2680
Willy Tarreau67402132012-05-31 20:40:20 +02002681 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002682 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2683 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002684 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002685 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002686
Willy Tarreau67402132012-05-31 20:40:20 +02002687 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002688 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2689 file, linenum);
2690 err_code |= ERR_ALERT | ERR_FATAL;
2691 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 }/* end else if (!strcmp(args[0], "cookie")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002693 else if (!strcmp(args[0], "persist")) { /* persist */
2694 if (*(args[1]) == 0) {
2695 Alert("parsing [%s:%d] : missing persist method.\n",
2696 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002697 err_code |= ERR_ALERT | ERR_FATAL;
2698 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002699 }
2700
2701 if (!strncmp(args[1], "rdp-cookie", 10)) {
2702 curproxy->options2 |= PR_O2_RDPC_PRST;
2703
Emeric Brunb982a3d2010-01-04 15:45:53 +01002704 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02002705 const char *beg, *end;
2706
2707 beg = args[1] + 11;
2708 end = strchr(beg, ')');
2709
2710 if (!end || end == beg) {
2711 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2712 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002715 }
2716
2717 free(curproxy->rdp_cookie_name);
2718 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
2719 curproxy->rdp_cookie_len = end-beg;
2720 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01002721 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02002722 free(curproxy->rdp_cookie_name);
2723 curproxy->rdp_cookie_name = strdup("msts");
2724 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
2725 }
2726 else { /* syntax */
2727 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
2728 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
2730 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002731 }
2732 }
2733 else {
2734 Alert("parsing [%s:%d] : unknown persist method.\n",
2735 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_ALERT | ERR_FATAL;
2737 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002738 }
2739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002741 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742
Cyril Bonté3b7a3692010-01-10 17:01:47 +01002743 if (curproxy == &defproxy) {
2744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2745 err_code |= ERR_ALERT | ERR_FATAL;
2746 goto out;
2747 }
2748
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002751
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002753 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002754 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002755 err_code |= ERR_ALERT | ERR_FATAL;
2756 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 }
2758 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002759 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002760 curproxy->appsession_name = strdup(args[1]);
2761 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
2762 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002763 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
2764 if (err) {
2765 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
2766 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002767 err_code |= ERR_ALERT | ERR_FATAL;
2768 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002769 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02002770 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02002771
Willy Tarreau51041c72007-09-09 21:56:53 +02002772 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
2773 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002774 err_code |= ERR_ALERT | ERR_ABORT;
2775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002776 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002777
2778 cur_arg = 6;
2779 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002780 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2781 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002782 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01002783 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002784 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01002785 } else if (!strcmp(args[cur_arg], "prefix")) {
2786 curproxy->options2 |= PR_O2_AS_PFX;
2787 } else if (!strcmp(args[cur_arg], "mode")) {
2788 if (!*args[cur_arg + 1]) {
2789 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
2790 file, linenum, args[0], args[cur_arg]);
2791 err_code |= ERR_ALERT | ERR_FATAL;
2792 goto out;
2793 }
2794
2795 cur_arg++;
2796 if (!strcmp(args[cur_arg], "query-string")) {
2797 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2798 curproxy->options2 |= PR_O2_AS_M_QS;
2799 } else if (!strcmp(args[cur_arg], "path-parameters")) {
2800 curproxy->options2 &= ~PR_O2_AS_M_ANY;
2801 curproxy->options2 |= PR_O2_AS_M_PP;
2802 } else {
2803 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
2804 err_code |= ERR_ALERT | ERR_FATAL;
2805 goto out;
2806 }
2807 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02002808 cur_arg++;
2809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002810 } /* Url App Session */
2811 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002812 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002813 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002814
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01002816 if (curproxy == &defproxy) {
2817 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
2818 err_code |= ERR_ALERT | ERR_FATAL;
2819 goto out;
2820 }
2821
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 if (*(args[4]) == 0) {
2823 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
2824 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002825 err_code |= ERR_ALERT | ERR_FATAL;
2826 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002827 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002828 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002829 curproxy->capture_name = strdup(args[2]);
2830 curproxy->capture_namelen = strlen(curproxy->capture_name);
2831 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 curproxy->to_log |= LW_COOKIE;
2833 }
2834 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
2835 struct cap_hdr *hdr;
2836
2837 if (curproxy == &defproxy) {
2838 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 +02002839 err_code |= ERR_ALERT | ERR_FATAL;
2840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002841 }
2842
2843 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2844 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2845 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002846 err_code |= ERR_ALERT | ERR_FATAL;
2847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002848 }
2849
2850 hdr = calloc(sizeof(struct cap_hdr), 1);
2851 hdr->next = curproxy->req_cap;
2852 hdr->name = strdup(args[3]);
2853 hdr->namelen = strlen(args[3]);
2854 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002855 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002856 hdr->index = curproxy->nb_req_cap++;
2857 curproxy->req_cap = hdr;
2858 curproxy->to_log |= LW_REQHDR;
2859 }
2860 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
2861 struct cap_hdr *hdr;
2862
2863 if (curproxy == &defproxy) {
2864 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 +02002865 err_code |= ERR_ALERT | ERR_FATAL;
2866 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867 }
2868
2869 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
2870 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
2871 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002872 err_code |= ERR_ALERT | ERR_FATAL;
2873 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 }
2875 hdr = calloc(sizeof(struct cap_hdr), 1);
2876 hdr->next = curproxy->rsp_cap;
2877 hdr->name = strdup(args[3]);
2878 hdr->namelen = strlen(args[3]);
2879 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02002880 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 hdr->index = curproxy->nb_rsp_cap++;
2882 curproxy->rsp_cap = hdr;
2883 curproxy->to_log |= LW_RSPHDR;
2884 }
2885 else {
2886 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
2887 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002888 err_code |= ERR_ALERT | ERR_FATAL;
2889 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
2891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002892 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002893 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002895
Willy Tarreaubaaee002006-06-26 02:48:02 +02002896 if (*(args[1]) == 0) {
2897 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
2898 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002899 err_code |= ERR_ALERT | ERR_FATAL;
2900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 }
2902 curproxy->conn_retries = atol(args[1]);
2903 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002904 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01002905 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002906
2907 if (curproxy == &defproxy) {
2908 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2909 err_code |= ERR_ALERT | ERR_FATAL;
2910 goto out;
2911 }
2912
Willy Tarreau20b0de52012-12-24 15:45:22 +01002913 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
2914 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
2915 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
2916 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002917 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01002918 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
2919 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 +01002920 file, linenum, args[0]);
2921 err_code |= ERR_WARN;
2922 }
2923
Willy Tarreauff011f22011-01-06 17:51:27 +01002924 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002925
Willy Tarreauff011f22011-01-06 17:51:27 +01002926 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002927 err_code |= ERR_ALERT | ERR_ABORT;
2928 goto out;
2929 }
2930
Willy Tarreau5002f572014-04-23 01:32:02 +02002931 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002932 err_code |= warnif_cond_conflicts(rule->cond,
2933 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
2934 file, linenum);
2935
Willy Tarreauff011f22011-01-06 17:51:27 +01002936 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01002937 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02002938 else if (!strcmp(args[0], "http-response")) { /* response access control */
2939 struct http_res_rule *rule;
2940
2941 if (curproxy == &defproxy) {
2942 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
2943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
2945 }
2946
2947 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
2948 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
2949 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
2950 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
2951 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
2952 file, linenum, args[0]);
2953 err_code |= ERR_WARN;
2954 }
2955
2956 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
2957
2958 if (!rule) {
2959 err_code |= ERR_ALERT | ERR_ABORT;
2960 goto out;
2961 }
2962
2963 err_code |= warnif_cond_conflicts(rule->cond,
2964 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
2965 file, linenum);
2966
2967 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
2968 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05002969 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
2970 /* set the header name and length into the proxy structure */
2971 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
2972 err_code |= ERR_WARN;
2973
2974 if (!*args[1]) {
2975 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
2976 file, linenum, args[0]);
2977 err_code |= ERR_ALERT | ERR_FATAL;
2978 goto out;
2979 }
2980
2981 /* set the desired header name */
2982 free(curproxy->server_id_hdr_name);
2983 curproxy->server_id_hdr_name = strdup(args[1]);
2984 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
2985 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02002986 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002987 struct http_req_rule *rule;
2988
Willy Tarreaub099aca2008-10-12 17:26:37 +02002989 if (curproxy == &defproxy) {
2990 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002991 err_code |= ERR_ALERT | ERR_FATAL;
2992 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002993 }
2994
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02002995 /* emulate "block" using "http-request block". Since these rules are supposed to
2996 * be processed before all http-request rules, we put them into their own list
2997 * and will insert them at the end.
2998 */
2999 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3000 if (!rule) {
3001 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003002 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003003 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003004 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3005 err_code |= warnif_cond_conflicts(rule->cond,
3006 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3007 file, linenum);
3008 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003009
3010 if (!already_warned(WARN_BLOCK_DEPRECATED))
3011 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]);
3012
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003013 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003014 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003015 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003016
Cyril Bonté99ed3272010-01-24 23:29:44 +01003017 if (curproxy == &defproxy) {
3018 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
3021 }
3022
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003023 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003024 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3025 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003028 }
3029
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003030 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003031 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003032 err_code |= warnif_cond_conflicts(rule->cond,
3033 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3034 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003035 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003036 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003037 struct switching_rule *rule;
3038
Willy Tarreaub099aca2008-10-12 17:26:37 +02003039 if (curproxy == &defproxy) {
3040 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003043 }
3044
Willy Tarreau55ea7572007-06-17 19:56:27 +02003045 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003046 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003047
3048 if (*(args[1]) == 0) {
3049 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003052 }
3053
Willy Tarreauf51658d2014-04-23 01:21:56 +02003054 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3055 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3056 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3057 file, linenum, errmsg);
3058 err_code |= ERR_ALERT | ERR_FATAL;
3059 goto out;
3060 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003061
Willy Tarreauf51658d2014-04-23 01:21:56 +02003062 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003063 }
3064
3065 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3066 rule->cond = cond;
3067 rule->be.name = strdup(args[1]);
3068 LIST_INIT(&rule->list);
3069 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3070 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003071 else if (strcmp(args[0], "use-server") == 0) {
3072 struct server_rule *rule;
3073
3074 if (curproxy == &defproxy) {
3075 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
3078 }
3079
3080 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3081 err_code |= ERR_WARN;
3082
3083 if (*(args[1]) == 0) {
3084 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3085 err_code |= ERR_ALERT | ERR_FATAL;
3086 goto out;
3087 }
3088
3089 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3090 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3091 file, linenum, args[0]);
3092 err_code |= ERR_ALERT | ERR_FATAL;
3093 goto out;
3094 }
3095
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003096 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3097 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3098 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003099 err_code |= ERR_ALERT | ERR_FATAL;
3100 goto out;
3101 }
3102
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003103 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003104
3105 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3106 rule->cond = cond;
3107 rule->srv.name = strdup(args[1]);
3108 LIST_INIT(&rule->list);
3109 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3110 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3111 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003112 else if ((!strcmp(args[0], "force-persist")) ||
3113 (!strcmp(args[0], "ignore-persist"))) {
3114 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003115
3116 if (curproxy == &defproxy) {
3117 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3118 err_code |= ERR_ALERT | ERR_FATAL;
3119 goto out;
3120 }
3121
3122 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3123 err_code |= ERR_WARN;
3124
Willy Tarreauef6494c2010-01-28 17:12:36 +01003125 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003126 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3127 file, linenum, args[0]);
3128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
3131
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003132 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3133 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3134 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003135 err_code |= ERR_ALERT | ERR_FATAL;
3136 goto out;
3137 }
3138
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003139 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3140 * where force-persist is applied.
3141 */
3142 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003143
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003144 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003145 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003146 if (!strcmp(args[0], "force-persist")) {
3147 rule->type = PERSIST_TYPE_FORCE;
3148 } else {
3149 rule->type = PERSIST_TYPE_IGNORE;
3150 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003151 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003152 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003153 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003154 else if (!strcmp(args[0], "stick-table")) {
3155 int myidx = 1;
3156
Emeric Brun32da3c42010-09-23 18:39:19 +02003157 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003158 curproxy->table.type = (unsigned int)-1;
3159 while (*args[myidx]) {
3160 const char *err;
3161
3162 if (strcmp(args[myidx], "size") == 0) {
3163 myidx++;
3164 if (!*(args[myidx])) {
3165 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3166 file, linenum, args[myidx-1]);
3167 err_code |= ERR_ALERT | ERR_FATAL;
3168 goto out;
3169 }
3170 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3171 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3172 file, linenum, *err, args[myidx-1]);
3173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
3175 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003176 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003177 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003178 else if (strcmp(args[myidx], "peers") == 0) {
3179 myidx++;
Godbach50523162013-12-11 19:48:57 +08003180 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003181 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3182 file, linenum, args[myidx-1]);
3183 err_code |= ERR_ALERT | ERR_FATAL;
3184 goto out;
Godbach50523162013-12-11 19:48:57 +08003185 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003186 curproxy->table.peers.name = strdup(args[myidx++]);
3187 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003188 else if (strcmp(args[myidx], "expire") == 0) {
3189 myidx++;
3190 if (!*(args[myidx])) {
3191 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3192 file, linenum, args[myidx-1]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
3196 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3197 if (err) {
3198 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3199 file, linenum, *err, args[myidx-1]);
3200 err_code |= ERR_ALERT | ERR_FATAL;
3201 goto out;
3202 }
3203 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003204 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003205 }
3206 else if (strcmp(args[myidx], "nopurge") == 0) {
3207 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003208 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003209 }
3210 else if (strcmp(args[myidx], "type") == 0) {
3211 myidx++;
3212 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3213 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3214 file, linenum, args[myidx]);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003218 /* myidx already points to next arg */
3219 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003220 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003221 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003222 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003223
3224 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003225 nw = args[myidx];
3226 while (*nw) {
3227 /* the "store" keyword supports a comma-separated list */
3228 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003229 sa = NULL; /* store arg */
3230 while (*nw && *nw != ',') {
3231 if (*nw == '(') {
3232 *nw = 0;
3233 sa = ++nw;
3234 while (*nw != ')') {
3235 if (!*nw) {
3236 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3237 file, linenum, args[0], cw);
3238 err_code |= ERR_ALERT | ERR_FATAL;
3239 goto out;
3240 }
3241 nw++;
3242 }
3243 *nw = '\0';
3244 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003245 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003246 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003247 if (*nw)
3248 *nw++ = '\0';
3249 type = stktable_get_data_type(cw);
3250 if (type < 0) {
3251 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3252 file, linenum, args[0], cw);
3253 err_code |= ERR_ALERT | ERR_FATAL;
3254 goto out;
3255 }
Willy Tarreauac782882010-06-20 10:41:54 +02003256
3257 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3258 switch (err) {
3259 case PE_NONE: break;
3260 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003261 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3262 file, linenum, args[0], cw);
3263 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003264 break;
3265
3266 case PE_ARG_MISSING:
3267 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3268 file, linenum, args[0], cw);
3269 err_code |= ERR_ALERT | ERR_FATAL;
3270 goto out;
3271
3272 case PE_ARG_NOT_USED:
3273 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3274 file, linenum, args[0], cw);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
3277
3278 default:
3279 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3280 file, linenum, args[0], cw);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003283 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003284 }
3285 myidx++;
3286 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003287 else {
3288 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3289 file, linenum, args[myidx]);
3290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003292 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003293 }
3294
3295 if (!curproxy->table.size) {
3296 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3297 file, linenum);
3298 err_code |= ERR_ALERT | ERR_FATAL;
3299 goto out;
3300 }
3301
3302 if (curproxy->table.type == (unsigned int)-1) {
3303 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3304 file, linenum);
3305 err_code |= ERR_ALERT | ERR_FATAL;
3306 goto out;
3307 }
3308 }
3309 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003310 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003311 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003312 int myidx = 0;
3313 const char *name = NULL;
3314 int flags;
3315
3316 if (curproxy == &defproxy) {
3317 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
3321
3322 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3323 err_code |= ERR_WARN;
3324 goto out;
3325 }
3326
3327 myidx++;
3328 if ((strcmp(args[myidx], "store") == 0) ||
3329 (strcmp(args[myidx], "store-request") == 0)) {
3330 myidx++;
3331 flags = STK_IS_STORE;
3332 }
3333 else if (strcmp(args[myidx], "store-response") == 0) {
3334 myidx++;
3335 flags = STK_IS_STORE | STK_ON_RSP;
3336 }
3337 else if (strcmp(args[myidx], "match") == 0) {
3338 myidx++;
3339 flags = STK_IS_MATCH;
3340 }
3341 else if (strcmp(args[myidx], "on") == 0) {
3342 myidx++;
3343 flags = STK_IS_MATCH | STK_IS_STORE;
3344 }
3345 else {
3346 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350
3351 if (*(args[myidx]) == 0) {
3352 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
3355 }
3356
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003357 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003358 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003359 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003360 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003361 err_code |= ERR_ALERT | ERR_FATAL;
3362 goto out;
3363 }
3364
3365 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003366 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3367 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3368 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003369 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003370 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003371 goto out;
3372 }
3373 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003374 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3375 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3376 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003377 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003378 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003379 goto out;
3380 }
3381 }
3382
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003383 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003384 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003385
Emeric Brunb982a3d2010-01-04 15:45:53 +01003386 if (strcmp(args[myidx], "table") == 0) {
3387 myidx++;
3388 name = args[myidx++];
3389 }
3390
Willy Tarreauef6494c2010-01-28 17:12:36 +01003391 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003392 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3393 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3394 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003395 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003396 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003397 goto out;
3398 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003399 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003400 else if (*(args[myidx])) {
3401 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3402 file, linenum, args[0], args[myidx]);
3403 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003404 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003405 goto out;
3406 }
Emeric Brun97679e72010-09-23 17:56:44 +02003407 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003408 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003409 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003410 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003411
Emeric Brunb982a3d2010-01-04 15:45:53 +01003412 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3413 rule->cond = cond;
3414 rule->expr = expr;
3415 rule->flags = flags;
3416 rule->table.name = name ? strdup(name) : NULL;
3417 LIST_INIT(&rule->list);
3418 if (flags & STK_ON_RSP)
3419 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3420 else
3421 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3422 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003423 else if (!strcmp(args[0], "stats")) {
3424 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3425 curproxy->uri_auth = NULL; /* we must detach from the default config */
3426
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003427 if (!*args[1]) {
3428 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003429 } else if (!strcmp(args[1], "admin")) {
3430 struct stats_admin_rule *rule;
3431
3432 if (curproxy == &defproxy) {
3433 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437
3438 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3439 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3440 err_code |= ERR_ALERT | ERR_ABORT;
3441 goto out;
3442 }
3443
3444 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3445 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3446 file, linenum, args[0], args[1]);
3447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
3449 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003450 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3451 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3452 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003453 err_code |= ERR_ALERT | ERR_FATAL;
3454 goto out;
3455 }
3456
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003457 err_code |= warnif_cond_conflicts(cond,
3458 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3459 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003460
3461 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3462 rule->cond = cond;
3463 LIST_INIT(&rule->list);
3464 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003465 } else if (!strcmp(args[1], "uri")) {
3466 if (*(args[2]) == 0) {
3467 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3471 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003472 err_code |= ERR_ALERT | ERR_ABORT;
3473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003474 }
3475 } else if (!strcmp(args[1], "realm")) {
3476 if (*(args[2]) == 0) {
3477 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3481 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003482 err_code |= ERR_ALERT | ERR_ABORT;
3483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003484 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003485 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003486 unsigned interval;
3487
3488 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3489 if (err) {
3490 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3491 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003494 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3495 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003496 err_code |= ERR_ALERT | ERR_ABORT;
3497 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003498 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003499 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003500 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003501
3502 if (curproxy == &defproxy) {
3503 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3504 err_code |= ERR_ALERT | ERR_FATAL;
3505 goto out;
3506 }
3507
3508 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3509 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3510 err_code |= ERR_ALERT | ERR_ABORT;
3511 goto out;
3512 }
3513
Willy Tarreauff011f22011-01-06 17:51:27 +01003514 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3515 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003516 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3517 file, linenum, args[0]);
3518 err_code |= ERR_WARN;
3519 }
3520
Willy Tarreauff011f22011-01-06 17:51:27 +01003521 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003522
Willy Tarreauff011f22011-01-06 17:51:27 +01003523 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003524 err_code |= ERR_ALERT | ERR_ABORT;
3525 goto out;
3526 }
3527
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003528 err_code |= warnif_cond_conflicts(rule->cond,
3529 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3530 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003531 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003532
Willy Tarreaubaaee002006-06-26 02:48:02 +02003533 } else if (!strcmp(args[1], "auth")) {
3534 if (*(args[2]) == 0) {
3535 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003538 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3539 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003540 err_code |= ERR_ALERT | ERR_ABORT;
3541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 }
3543 } else if (!strcmp(args[1], "scope")) {
3544 if (*(args[2]) == 0) {
3545 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003546 err_code |= ERR_ALERT | ERR_FATAL;
3547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003548 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3549 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003550 err_code |= ERR_ALERT | ERR_ABORT;
3551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 }
3553 } else if (!strcmp(args[1], "enable")) {
3554 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3555 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003556 err_code |= ERR_ALERT | ERR_ABORT;
3557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003558 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003559 } else if (!strcmp(args[1], "hide-version")) {
3560 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3561 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_ALERT | ERR_ABORT;
3563 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003564 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003565 } else if (!strcmp(args[1], "show-legends")) {
3566 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3567 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3568 err_code |= ERR_ALERT | ERR_ABORT;
3569 goto out;
3570 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003571 } else if (!strcmp(args[1], "show-node")) {
3572
3573 if (*args[2]) {
3574 int i;
3575 char c;
3576
3577 for (i=0; args[2][i]; i++) {
3578 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003579 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3580 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003581 break;
3582 }
3583
3584 if (!i || args[2][i]) {
3585 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3586 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3587 file, linenum, args[0], args[1]);
3588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
3590 }
3591 }
3592
3593 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3594 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3595 err_code |= ERR_ALERT | ERR_ABORT;
3596 goto out;
3597 }
3598 } else if (!strcmp(args[1], "show-desc")) {
3599 char *desc = NULL;
3600
3601 if (*args[2]) {
3602 int i, len=0;
3603 char *d;
3604
Willy Tarreau348acfe2014-04-14 15:00:39 +02003605 for (i = 2; *args[i]; i++)
3606 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003607
3608 desc = d = (char *)calloc(1, len);
3609
Willy Tarreau348acfe2014-04-14 15:00:39 +02003610 d += snprintf(d, desc + len - d, "%s", args[2]);
3611 for (i = 3; *args[i]; i++)
3612 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003613 }
3614
3615 if (!*args[2] && !global.desc)
3616 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3617 file, linenum, args[1]);
3618 else {
3619 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3620 free(desc);
3621 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3622 err_code |= ERR_ALERT | ERR_ABORT;
3623 goto out;
3624 }
3625 free(desc);
3626 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003627 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003628stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003629 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 +01003630 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
3634 }
3635 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003636 int optnum;
3637
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003638 if (*(args[1]) == '\0') {
3639 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3640 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003641 err_code |= ERR_ALERT | ERR_FATAL;
3642 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003643 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003644
3645 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3646 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003647 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3648 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3649 file, linenum, cfg_opts[optnum].name);
3650 err_code |= ERR_ALERT | ERR_FATAL;
3651 goto out;
3652 }
Willy Tarreau93893792009-07-23 13:19:11 +02003653 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3654 err_code |= ERR_WARN;
3655 goto out;
3656 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003657
Willy Tarreau3842f002009-06-14 11:39:52 +02003658 curproxy->no_options &= ~cfg_opts[optnum].val;
3659 curproxy->options &= ~cfg_opts[optnum].val;
3660
3661 switch (kwm) {
3662 case KWM_STD:
3663 curproxy->options |= cfg_opts[optnum].val;
3664 break;
3665 case KWM_NO:
3666 curproxy->no_options |= cfg_opts[optnum].val;
3667 break;
3668 case KWM_DEF: /* already cleared */
3669 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003670 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003671
Willy Tarreau93893792009-07-23 13:19:11 +02003672 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003673 }
3674 }
3675
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003676 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3677 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003678 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3679 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3680 file, linenum, cfg_opts2[optnum].name);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
Willy Tarreau93893792009-07-23 13:19:11 +02003684 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3685 err_code |= ERR_WARN;
3686 goto out;
3687 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003688
Willy Tarreau3842f002009-06-14 11:39:52 +02003689 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3690 curproxy->options2 &= ~cfg_opts2[optnum].val;
3691
3692 switch (kwm) {
3693 case KWM_STD:
3694 curproxy->options2 |= cfg_opts2[optnum].val;
3695 break;
3696 case KWM_NO:
3697 curproxy->no_options2 |= cfg_opts2[optnum].val;
3698 break;
3699 case KWM_DEF: /* already cleared */
3700 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003701 }
Willy Tarreau93893792009-07-23 13:19:11 +02003702 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003703 }
3704 }
3705
Willy Tarreau02bce8b2014-01-30 00:15:28 +01003706 /* HTTP options override each other. They can be cancelled using
3707 * "no option xxx" which only switches to default mode if the mode
3708 * was this one (useful for cancelling options set in defaults
3709 * sections).
3710 */
3711 if (strcmp(args[1], "httpclose") == 0) {
3712 if (kwm == KWM_STD) {
3713 curproxy->options &= ~PR_O_HTTP_MODE;
3714 curproxy->options |= PR_O_HTTP_PCL;
3715 goto out;
3716 }
3717 else if (kwm == KWM_NO) {
3718 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
3719 curproxy->options &= ~PR_O_HTTP_MODE;
3720 goto out;
3721 }
3722 }
3723 else if (strcmp(args[1], "forceclose") == 0) {
3724 if (kwm == KWM_STD) {
3725 curproxy->options &= ~PR_O_HTTP_MODE;
3726 curproxy->options |= PR_O_HTTP_FCL;
3727 goto out;
3728 }
3729 else if (kwm == KWM_NO) {
3730 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
3731 curproxy->options &= ~PR_O_HTTP_MODE;
3732 goto out;
3733 }
3734 }
3735 else if (strcmp(args[1], "http-server-close") == 0) {
3736 if (kwm == KWM_STD) {
3737 curproxy->options &= ~PR_O_HTTP_MODE;
3738 curproxy->options |= PR_O_HTTP_SCL;
3739 goto out;
3740 }
3741 else if (kwm == KWM_NO) {
3742 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
3743 curproxy->options &= ~PR_O_HTTP_MODE;
3744 goto out;
3745 }
3746 }
3747 else if (strcmp(args[1], "http-keep-alive") == 0) {
3748 if (kwm == KWM_STD) {
3749 curproxy->options &= ~PR_O_HTTP_MODE;
3750 curproxy->options |= PR_O_HTTP_KAL;
3751 goto out;
3752 }
3753 else if (kwm == KWM_NO) {
3754 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
3755 curproxy->options &= ~PR_O_HTTP_MODE;
3756 goto out;
3757 }
3758 }
3759 else if (strcmp(args[1], "http-tunnel") == 0) {
3760 if (kwm == KWM_STD) {
3761 curproxy->options &= ~PR_O_HTTP_MODE;
3762 curproxy->options |= PR_O_HTTP_TUN;
3763 goto out;
3764 }
3765 else if (kwm == KWM_NO) {
3766 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
3767 curproxy->options &= ~PR_O_HTTP_MODE;
3768 goto out;
3769 }
3770 }
3771
Willy Tarreau3842f002009-06-14 11:39:52 +02003772 if (kwm != KWM_STD) {
3773 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003774 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003775 err_code |= ERR_ALERT | ERR_FATAL;
3776 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003777 }
3778
Emeric Brun3a058f32009-06-30 18:26:00 +02003779 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01003780 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003781 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01003782 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003783 if (*(args[2]) != '\0') {
3784 if (!strcmp(args[2], "clf")) {
3785 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01003786 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02003787 } else {
3788 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02003789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02003791 }
3792 }
Willy Tarreau62a61232013-04-12 18:13:46 +02003793 if (curproxy->conf.logformat_string != default_http_log_format &&
3794 curproxy->conf.logformat_string != default_tcp_log_format &&
3795 curproxy->conf.logformat_string != clf_http_log_format)
3796 free(curproxy->conf.logformat_string);
3797 curproxy->conf.logformat_string = logformat;
3798
3799 free(curproxy->conf.lfs_file);
3800 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3801 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02003802 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01003803 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003804 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02003805 if (curproxy->conf.logformat_string != default_http_log_format &&
3806 curproxy->conf.logformat_string != default_tcp_log_format &&
3807 curproxy->conf.logformat_string != clf_http_log_format)
3808 free(curproxy->conf.logformat_string);
3809 curproxy->conf.logformat_string = default_tcp_log_format;
3810
3811 free(curproxy->conf.lfs_file);
3812 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
3813 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01003814 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003815 else if (!strcmp(args[1], "tcpka")) {
3816 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003817 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003818 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003819
3820 if (curproxy->cap & PR_CAP_FE)
3821 curproxy->options |= PR_O_TCP_CLI_KA;
3822 if (curproxy->cap & PR_CAP_BE)
3823 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003824 }
3825 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003826 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_WARN;
3828
Willy Tarreaubaaee002006-06-26 02:48:02 +02003829 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003830 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003831 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003832 curproxy->options2 &= ~PR_O2_CHK_ANY;
3833 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 if (!*args[2]) { /* no argument */
3835 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
3836 curproxy->check_len = strlen(DEF_CHECK_REQ);
3837 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003838 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 curproxy->check_req = (char *)malloc(reqlen);
3840 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003841 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02003842 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01003843 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 if (*args[4])
3845 reqlen += strlen(args[4]);
3846 else
3847 reqlen += strlen("HTTP/1.0");
3848
3849 curproxy->check_req = (char *)malloc(reqlen);
3850 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01003851 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02003852 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02003853 }
3854 else if (!strcmp(args[1], "ssl-hello-chk")) {
3855 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01003856 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003857 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003858
Willy Tarreaua534fea2008-08-03 12:19:50 +02003859 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003860 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003861 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02003862 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003863 }
Willy Tarreau23677902007-05-08 23:50:35 +02003864 else if (!strcmp(args[1], "smtpchk")) {
3865 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02003866 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003867 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003868 curproxy->options2 &= ~PR_O2_CHK_ANY;
3869 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02003870
3871 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
3872 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3873 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3874 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
3875 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
3876 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
3877 curproxy->check_req = (char *)malloc(reqlen);
3878 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
3879 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
3880 } else {
3881 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
3882 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
3883 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
3884 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
3885 }
3886 }
3887 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003888 else if (!strcmp(args[1], "pgsql-check")) {
3889 /* use PostgreSQL request to check servers' health */
3890 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3891 err_code |= ERR_WARN;
3892
3893 free(curproxy->check_req);
3894 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003895 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01003896 curproxy->options2 |= PR_O2_PGSQL_CHK;
3897
3898 if (*(args[2])) {
3899 int cur_arg = 2;
3900
3901 while (*(args[cur_arg])) {
3902 if (strcmp(args[cur_arg], "user") == 0) {
3903 char * packet;
3904 uint32_t packet_len;
3905 uint32_t pv;
3906
3907 /* suboption header - needs additional argument for it */
3908 if (*(args[cur_arg+1]) == 0) {
3909 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
3910 file, linenum, args[0], args[1], args[cur_arg]);
3911 err_code |= ERR_ALERT | ERR_FATAL;
3912 goto out;
3913 }
3914
3915 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
3916 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
3917 pv = htonl(0x30000); /* protocol version 3.0 */
3918
3919 packet = (char*) calloc(1, packet_len);
3920
3921 memcpy(packet + 4, &pv, 4);
3922
3923 /* copy "user" */
3924 memcpy(packet + 8, "user", 4);
3925
3926 /* copy username */
3927 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
3928
3929 free(curproxy->check_req);
3930 curproxy->check_req = packet;
3931 curproxy->check_len = packet_len;
3932
3933 packet_len = htonl(packet_len);
3934 memcpy(packet, &packet_len, 4);
3935 cur_arg += 2;
3936 } else {
3937 /* unknown suboption - catchall */
3938 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
3939 file, linenum, args[0], args[1]);
3940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
3942 }
3943 } /* end while loop */
3944 }
3945 }
3946
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003947 else if (!strcmp(args[1], "redis-check")) {
3948 /* use REDIS PING request to check servers' health */
3949 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3950 err_code |= ERR_WARN;
3951
3952 free(curproxy->check_req);
3953 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003954 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02003955 curproxy->options2 |= PR_O2_REDIS_CHK;
3956
3957 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
3958 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
3959 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
3960 }
3961
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003962 else if (!strcmp(args[1], "mysql-check")) {
3963 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003964 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
3965 err_code |= ERR_WARN;
3966
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003967 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01003968 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02003969 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01003970 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003971
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003972 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02003973 * const char mysql40_client_auth_pkt[] = {
3974 * "\x0e\x00\x00" // packet length
3975 * "\x01" // packet number
3976 * "\x00\x00" // client capabilities
3977 * "\x00\x00\x01" // max packet
3978 * "haproxy\x00" // username (null terminated string)
3979 * "\x00" // filler (always 0x00)
3980 * "\x01\x00\x00" // packet length
3981 * "\x00" // packet number
3982 * "\x01" // COM_QUIT command
3983 * };
3984 */
3985
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02003986 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
3987 * const char mysql41_client_auth_pkt[] = {
3988 * "\x0e\x00\x00\" // packet length
3989 * "\x01" // packet number
3990 * "\x00\x00\x00\x00" // client capabilities
3991 * "\x00\x00\x00\x01" // max packet
3992 * "\x21" // character set (UTF-8)
3993 * char[23] // All zeroes
3994 * "haproxy\x00" // username (null terminated string)
3995 * "\x00" // filler (always 0x00)
3996 * "\x01\x00\x00" // packet length
3997 * "\x00" // packet number
3998 * "\x01" // COM_QUIT command
3999 * };
4000 */
4001
4002
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004003 if (*(args[2])) {
4004 int cur_arg = 2;
4005
4006 while (*(args[cur_arg])) {
4007 if (strcmp(args[cur_arg], "user") == 0) {
4008 char *mysqluser;
4009 int packetlen, reqlen, userlen;
4010
4011 /* suboption header - needs additional argument for it */
4012 if (*(args[cur_arg+1]) == 0) {
4013 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4014 file, linenum, args[0], args[1], args[cur_arg]);
4015 err_code |= ERR_ALERT | ERR_FATAL;
4016 goto out;
4017 }
4018 mysqluser = args[cur_arg + 1];
4019 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004020
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004021 if (*(args[cur_arg+2])) {
4022 if (!strcmp(args[cur_arg+2], "post-41")) {
4023 packetlen = userlen + 7 + 27;
4024 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004025
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004026 free(curproxy->check_req);
4027 curproxy->check_req = (char *)calloc(1, reqlen);
4028 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004029
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004030 snprintf(curproxy->check_req, 4, "%c%c%c",
4031 ((unsigned char) packetlen & 0xff),
4032 ((unsigned char) (packetlen >> 8) & 0xff),
4033 ((unsigned char) (packetlen >> 16) & 0xff));
4034
4035 curproxy->check_req[3] = 1;
4036 curproxy->check_req[5] = 130;
4037 curproxy->check_req[11] = 1;
4038 curproxy->check_req[12] = 33;
4039 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4040 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4041 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4042 cur_arg += 3;
4043 } else {
4044 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
4047 }
4048 } else {
4049 packetlen = userlen + 7;
4050 reqlen = packetlen + 9;
4051
4052 free(curproxy->check_req);
4053 curproxy->check_req = (char *)calloc(1, reqlen);
4054 curproxy->check_len = reqlen;
4055
4056 snprintf(curproxy->check_req, 4, "%c%c%c",
4057 ((unsigned char) packetlen & 0xff),
4058 ((unsigned char) (packetlen >> 8) & 0xff),
4059 ((unsigned char) (packetlen >> 16) & 0xff));
4060
4061 curproxy->check_req[3] = 1;
4062 curproxy->check_req[5] = 128;
4063 curproxy->check_req[8] = 1;
4064 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4065 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4066 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4067 cur_arg += 2;
4068 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004069 } else {
4070 /* unknown suboption - catchall */
4071 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4072 file, linenum, args[0], args[1]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076 } /* end while loop */
4077 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004078 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004079 else if (!strcmp(args[1], "ldap-check")) {
4080 /* use LDAP request to check servers' health */
4081 free(curproxy->check_req);
4082 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004083 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004084 curproxy->options2 |= PR_O2_LDAP_CHK;
4085
4086 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4087 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4088 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4089 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004090 else if (!strcmp(args[1], "tcp-check")) {
4091 /* use raw TCPCHK send/expect to check servers' health */
4092 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4093 err_code |= ERR_WARN;
4094
4095 free(curproxy->check_req);
4096 curproxy->check_req = NULL;
4097 curproxy->options2 &= ~PR_O2_CHK_ANY;
4098 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4099 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004100 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004101 int cur_arg;
4102
4103 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4104 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004105 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004106
Willy Tarreau87cf5142011-08-19 22:57:24 +02004107 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004108
4109 free(curproxy->fwdfor_hdr_name);
4110 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4111 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4112
4113 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4114 cur_arg = 2;
4115 while (*(args[cur_arg])) {
4116 if (!strcmp(args[cur_arg], "except")) {
4117 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004118 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004119 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4120 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004121 err_code |= ERR_ALERT | ERR_FATAL;
4122 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004123 }
4124 /* flush useless bits */
4125 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004126 cur_arg += 2;
4127 } else if (!strcmp(args[cur_arg], "header")) {
4128 /* suboption header - needs additional argument for it */
4129 if (*(args[cur_arg+1]) == 0) {
4130 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4131 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004134 }
4135 free(curproxy->fwdfor_hdr_name);
4136 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4137 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4138 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004139 } else if (!strcmp(args[cur_arg], "if-none")) {
4140 curproxy->options &= ~PR_O_FF_ALWAYS;
4141 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004142 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004143 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004144 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004145 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004146 err_code |= ERR_ALERT | ERR_FATAL;
4147 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004148 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004149 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004150 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004151 else if (!strcmp(args[1], "originalto")) {
4152 int cur_arg;
4153
4154 /* insert x-original-to field, but not for the IP address listed as an except.
4155 * set default options (ie: bitfield, header name, etc)
4156 */
4157
4158 curproxy->options |= PR_O_ORGTO;
4159
4160 free(curproxy->orgto_hdr_name);
4161 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4162 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4163
Willy Tarreau87cf5142011-08-19 22:57:24 +02004164 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004165 cur_arg = 2;
4166 while (*(args[cur_arg])) {
4167 if (!strcmp(args[cur_arg], "except")) {
4168 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004169 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 +02004170 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4171 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004172 err_code |= ERR_ALERT | ERR_FATAL;
4173 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004174 }
4175 /* flush useless bits */
4176 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4177 cur_arg += 2;
4178 } else if (!strcmp(args[cur_arg], "header")) {
4179 /* suboption header - needs additional argument for it */
4180 if (*(args[cur_arg+1]) == 0) {
4181 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4182 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004185 }
4186 free(curproxy->orgto_hdr_name);
4187 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4188 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4189 cur_arg += 2;
4190 } else {
4191 /* unknown suboption - catchall */
4192 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4193 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004194 err_code |= ERR_ALERT | ERR_FATAL;
4195 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004196 }
4197 } /* end while loop */
4198 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 else {
4200 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004201 err_code |= ERR_ALERT | ERR_FATAL;
4202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004203 }
Willy Tarreau93893792009-07-23 13:19:11 +02004204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004205 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004206 else if (!strcmp(args[0], "default_backend")) {
4207 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004208 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004209
4210 if (*(args[1]) == 0) {
4211 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004214 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004215 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004216 curproxy->defbe.name = strdup(args[1]);
4217 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004218 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004219 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004220 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004221
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004222 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4223 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 +01004224 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004225 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004226 /* enable reconnections to dispatch */
4227 curproxy->options |= PR_O_REDISP;
4228 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004229 else if (!strcmp(args[0], "http-check")) {
4230 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004231 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004232
4233 if (strcmp(args[1], "disable-on-404") == 0) {
4234 /* enable a graceful server shutdown on an HTTP 404 response */
4235 curproxy->options |= PR_O_DISABLE404;
4236 }
Willy Tarreauef781042010-01-27 11:53:01 +01004237 else if (strcmp(args[1], "send-state") == 0) {
4238 /* enable emission of the apparent state of a server in HTTP checks */
4239 curproxy->options2 |= PR_O2_CHK_SNDST;
4240 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004241 else if (strcmp(args[1], "expect") == 0) {
4242 const char *ptr_arg;
4243 int cur_arg;
4244
4245 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4246 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
4249 }
4250
4251 cur_arg = 2;
4252 /* consider exclamation marks, sole or at the beginning of a word */
4253 while (*(ptr_arg = args[cur_arg])) {
4254 while (*ptr_arg == '!') {
4255 curproxy->options2 ^= PR_O2_EXP_INV;
4256 ptr_arg++;
4257 }
4258 if (*ptr_arg)
4259 break;
4260 cur_arg++;
4261 }
4262 /* now ptr_arg points to the beginning of a word past any possible
4263 * exclamation mark, and cur_arg is the argument which holds this word.
4264 */
4265 if (strcmp(ptr_arg, "status") == 0) {
4266 if (!*(args[cur_arg + 1])) {
4267 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4268 file, linenum, args[0], args[1], ptr_arg);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004273 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004274 curproxy->expect_str = strdup(args[cur_arg + 1]);
4275 }
4276 else if (strcmp(ptr_arg, "string") == 0) {
4277 if (!*(args[cur_arg + 1])) {
4278 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4279 file, linenum, args[0], args[1], ptr_arg);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004284 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004285 curproxy->expect_str = strdup(args[cur_arg + 1]);
4286 }
4287 else if (strcmp(ptr_arg, "rstatus") == 0) {
4288 if (!*(args[cur_arg + 1])) {
4289 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4290 file, linenum, args[0], args[1], ptr_arg);
4291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
4293 }
4294 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004295 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004296 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004297 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004298 free(curproxy->expect_regex);
4299 curproxy->expect_regex = NULL;
4300 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004301 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004302 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4303 error = NULL;
4304 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4305 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4306 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4307 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004308 err_code |= ERR_ALERT | ERR_FATAL;
4309 goto out;
4310 }
4311 }
4312 else if (strcmp(ptr_arg, "rstring") == 0) {
4313 if (!*(args[cur_arg + 1])) {
4314 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4315 file, linenum, args[0], args[1], ptr_arg);
4316 err_code |= ERR_ALERT | ERR_FATAL;
4317 goto out;
4318 }
4319 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004320 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004321 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004322 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004323 free(curproxy->expect_regex);
4324 curproxy->expect_regex = NULL;
4325 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004326 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004327 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4328 error = NULL;
4329 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4330 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4331 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4332 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004333 err_code |= ERR_ALERT | ERR_FATAL;
4334 goto out;
4335 }
4336 }
4337 else {
4338 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4339 file, linenum, args[0], args[1], ptr_arg);
4340 err_code |= ERR_ALERT | ERR_FATAL;
4341 goto out;
4342 }
4343 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004344 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004345 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 +02004346 err_code |= ERR_ALERT | ERR_FATAL;
4347 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004348 }
4349 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004350 else if (!strcmp(args[0], "tcp-check")) {
4351 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4352 err_code |= ERR_WARN;
4353
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004354 if (strcmp(args[1], "connect") == 0) {
4355 const char *ptr_arg;
4356 int cur_arg;
4357 struct tcpcheck_rule *tcpcheck;
4358 struct list *l;
4359
4360 /* check if first rule is also a 'connect' action */
4361 l = (struct list *)&curproxy->tcpcheck_rules;
4362 if (l->p != l->n) {
4363 tcpcheck = (struct tcpcheck_rule *)l->n;
4364 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4365 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4366 file, linenum);
4367 err_code |= ERR_ALERT | ERR_FATAL;
4368 goto out;
4369 }
4370 }
4371
4372 cur_arg = 2;
4373 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4374 tcpcheck->action = TCPCHK_ACT_CONNECT;
4375
4376 /* parsing each parameters to fill up the rule */
4377 while (*(ptr_arg = args[cur_arg])) {
4378 /* tcp port */
4379 if (strcmp(args[cur_arg], "port") == 0) {
4380 if ( (atol(args[cur_arg + 1]) > 65535) ||
4381 (atol(args[cur_arg + 1]) < 1) ){
4382 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4383 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
4386 }
4387 tcpcheck->port = atol(args[cur_arg + 1]);
4388 cur_arg += 2;
4389 }
4390 /* send proxy protocol */
4391 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4392 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4393 cur_arg++;
4394 }
4395#ifdef USE_OPENSSL
4396 else if (strcmp(args[cur_arg], "ssl") == 0) {
4397 curproxy->options |= PR_O_TCPCHK_SSL;
4398 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4399 cur_arg++;
4400 }
4401#endif /* USE_OPENSSL */
4402 else {
4403#ifdef USE_OPENSSL
4404 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4405#else /* USE_OPENSSL */
4406 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4407#endif /* USE_OPENSSL */
4408 file, linenum, args[0], args[1], args[cur_arg]);
4409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
4411 }
4412
4413 }
4414
4415 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4416 }
4417 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004418 if (! *(args[2]) ) {
4419 /* SEND string expected */
4420 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4421 file, linenum, args[0], args[1], args[2]);
4422 err_code |= ERR_ALERT | ERR_FATAL;
4423 goto out;
4424 } else {
4425 struct tcpcheck_rule *tcpcheck;
4426
4427 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4428
4429 tcpcheck->action = TCPCHK_ACT_SEND;
4430 tcpcheck->string_len = strlen(args[2]);
4431 tcpcheck->string = strdup(args[2]);
4432 tcpcheck->expect_regex = NULL;
4433
4434 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4435 }
4436 }
4437 else if (strcmp(args[1], "send-binary") == 0) {
4438 if (! *(args[2]) ) {
4439 /* SEND binary string expected */
4440 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4441 file, linenum, args[0], args[1], args[2]);
4442 err_code |= ERR_ALERT | ERR_FATAL;
4443 goto out;
4444 } else {
4445 struct tcpcheck_rule *tcpcheck;
4446 char *err = NULL;
4447
4448 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4449
4450 tcpcheck->action = TCPCHK_ACT_SEND;
4451 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4452 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4453 file, linenum, args[0], args[1], args[2], err);
4454 err_code |= ERR_ALERT | ERR_FATAL;
4455 goto out;
4456 }
4457 tcpcheck->expect_regex = NULL;
4458
4459 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4460 }
4461 }
4462 else if (strcmp(args[1], "expect") == 0) {
4463 const char *ptr_arg;
4464 int cur_arg;
4465 int inverse = 0;
4466
4467 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4468 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4469 err_code |= ERR_ALERT | ERR_FATAL;
4470 goto out;
4471 }
4472
4473 cur_arg = 2;
4474 /* consider exclamation marks, sole or at the beginning of a word */
4475 while (*(ptr_arg = args[cur_arg])) {
4476 while (*ptr_arg == '!') {
4477 inverse = !inverse;
4478 ptr_arg++;
4479 }
4480 if (*ptr_arg)
4481 break;
4482 cur_arg++;
4483 }
4484 /* now ptr_arg points to the beginning of a word past any possible
4485 * exclamation mark, and cur_arg is the argument which holds this word.
4486 */
4487 if (strcmp(ptr_arg, "binary") == 0) {
4488 if (!*(args[cur_arg + 1])) {
4489 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4490 file, linenum, args[0], args[1], ptr_arg);
4491 err_code |= ERR_ALERT | ERR_FATAL;
4492 goto out;
4493 }
4494 struct tcpcheck_rule *tcpcheck;
4495 char *err = NULL;
4496
4497 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4498
4499 tcpcheck->action = TCPCHK_ACT_EXPECT;
4500 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4501 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4502 file, linenum, args[0], args[1], args[2], err);
4503 err_code |= ERR_ALERT | ERR_FATAL;
4504 goto out;
4505 }
4506 tcpcheck->expect_regex = NULL;
4507 tcpcheck->inverse = inverse;
4508
4509 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4510 }
4511 else if (strcmp(ptr_arg, "string") == 0) {
4512 if (!*(args[cur_arg + 1])) {
4513 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4514 file, linenum, args[0], args[1], ptr_arg);
4515 err_code |= ERR_ALERT | ERR_FATAL;
4516 goto out;
4517 }
4518 struct tcpcheck_rule *tcpcheck;
4519
4520 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4521
4522 tcpcheck->action = TCPCHK_ACT_EXPECT;
4523 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4524 tcpcheck->string = strdup(args[cur_arg + 1]);
4525 tcpcheck->expect_regex = NULL;
4526 tcpcheck->inverse = inverse;
4527
4528 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4529 }
4530 else if (strcmp(ptr_arg, "rstring") == 0) {
4531 if (!*(args[cur_arg + 1])) {
4532 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4533 file, linenum, args[0], args[1], ptr_arg);
4534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
4536 }
4537 struct tcpcheck_rule *tcpcheck;
4538
4539 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4540
4541 tcpcheck->action = TCPCHK_ACT_EXPECT;
4542 tcpcheck->string_len = 0;
4543 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004544 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4545 error = NULL;
4546 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4547 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4548 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4549 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
4552 }
4553 tcpcheck->inverse = inverse;
4554
4555 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4556 }
4557 else {
4558 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4559 file, linenum, args[0], args[1], ptr_arg);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
4563 }
4564 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004565 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
4569 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004570 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004571 if (curproxy == &defproxy) {
4572 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004573 err_code |= ERR_ALERT | ERR_FATAL;
4574 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004575 }
4576
Willy Tarreaub80c2302007-11-30 20:51:32 +01004577 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004578 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004579
4580 if (strcmp(args[1], "fail") == 0) {
4581 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004582 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004583 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4584 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004587 }
4588
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004589 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4590 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4591 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004592 err_code |= ERR_ALERT | ERR_FATAL;
4593 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004594 }
4595 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4596 }
4597 else {
4598 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004599 err_code |= ERR_ALERT | ERR_FATAL;
4600 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004601 }
4602 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004603#ifdef TPROXY
4604 else if (!strcmp(args[0], "transparent")) {
4605 /* enable transparent proxy connections */
4606 curproxy->options |= PR_O_TRANSP;
4607 }
4608#endif
4609 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004610 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004611 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004612
Willy Tarreaubaaee002006-06-26 02:48:02 +02004613 if (*(args[1]) == 0) {
4614 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004615 err_code |= ERR_ALERT | ERR_FATAL;
4616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004617 }
4618 curproxy->maxconn = atol(args[1]);
4619 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004620 else if (!strcmp(args[0], "backlog")) { /* backlog */
4621 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004622 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004623
4624 if (*(args[1]) == 0) {
4625 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004626 err_code |= ERR_ALERT | ERR_FATAL;
4627 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004628 }
4629 curproxy->backlog = atol(args[1]);
4630 }
Willy Tarreau86034312006-12-29 00:10:33 +01004631 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004632 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004633 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004634
Willy Tarreau86034312006-12-29 00:10:33 +01004635 if (*(args[1]) == 0) {
4636 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004637 err_code |= ERR_ALERT | ERR_FATAL;
4638 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004639 }
4640 curproxy->fullconn = atol(args[1]);
4641 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004642 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4643 if (*(args[1]) == 0) {
4644 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004647 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004648 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4649 if (err) {
4650 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4651 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004654 }
4655 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004656 }
4657 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004658 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004659 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004660 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004661
Willy Tarreaubaaee002006-06-26 02:48:02 +02004662 if (curproxy == &defproxy) {
4663 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004664 err_code |= ERR_ALERT | ERR_FATAL;
4665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004666 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004667 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004668 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004669
Willy Tarreau902636f2013-03-10 19:44:48 +01004670 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004671 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004672 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004673 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004674 goto out;
4675 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004676
4677 proto = protocol_by_family(sk->ss_family);
4678 if (!proto || !proto->connect) {
4679 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4680 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004681 err_code |= ERR_ALERT | ERR_FATAL;
4682 goto out;
4683 }
4684
4685 if (port1 != port2) {
4686 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4687 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004688 err_code |= ERR_ALERT | ERR_FATAL;
4689 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004690 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004691
4692 if (!port1) {
4693 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
4694 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004695 err_code |= ERR_ALERT | ERR_FATAL;
4696 goto out;
4697 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004698
Willy Tarreaud5191e72010-02-09 20:50:45 +01004699 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004700 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004701 }
4702 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004703 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004704 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004705
Willy Tarreaua93c74b2012-05-08 18:14:39 +02004706 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
4707 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02004710 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004711 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004712 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004713 /**
4714 * The syntax for hash-type config element is
4715 * hash-type {map-based|consistent} [[<algo>] avalanche]
4716 *
4717 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
4718 */
4719 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04004720
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004721 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4722 err_code |= ERR_WARN;
4723
4724 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004725 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
4726 }
4727 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004728 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
4729 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004730 else if (strcmp(args[1], "avalanche") == 0) {
4731 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]);
4732 err_code |= ERR_ALERT | ERR_FATAL;
4733 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01004734 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004735 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004736 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02004737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
4739 }
Bhaskar98634f02013-10-29 23:30:51 -04004740
4741 /* set the hash function to use */
4742 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004743 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04004744 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004745
4746 /* if consistent with no argument, then avalanche modifier is also applied */
4747 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
4748 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04004749 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004750 /* set the hash function */
4751 if (!strcmp(args[2], "sdbm")) {
4752 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
4753 }
4754 else if (!strcmp(args[2], "djb2")) {
4755 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreaua0f42712013-11-14 14:30:35 +01004756 } else if (!strcmp(args[2], "wt6")) {
4757 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05004758 }
4759 else {
Willy Tarreaua0f42712013-11-14 14:30:35 +01004760 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 -05004761 err_code |= ERR_ALERT | ERR_FATAL;
4762 goto out;
4763 }
4764
4765 /* set the hash modifier */
4766 if (!strcmp(args[3], "avalanche")) {
4767 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
4768 }
4769 else if (*args[3]) {
4770 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
4771 err_code |= ERR_ALERT | ERR_FATAL;
4772 goto out;
4773 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01004774 }
William Lallemanda73203e2012-03-12 12:48:57 +01004775 }
William Lallemanda73203e2012-03-12 12:48:57 +01004776 else if (strcmp(args[0], "unique-id-format") == 0) {
4777 if (!*(args[1])) {
4778 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4779 err_code |= ERR_ALERT | ERR_FATAL;
4780 goto out;
4781 }
William Lallemand3203ff42012-11-11 17:30:56 +01004782 if (*(args[2])) {
4783 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4784 err_code |= ERR_ALERT | ERR_FATAL;
4785 goto out;
4786 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004787 free(curproxy->conf.uniqueid_format_string);
4788 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004789
Willy Tarreau62a61232013-04-12 18:13:46 +02004790 free(curproxy->conf.uif_file);
4791 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
4792 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01004793 }
William Lallemanda73203e2012-03-12 12:48:57 +01004794
4795 else if (strcmp(args[0], "unique-id-header") == 0) {
4796 if (!*(args[1])) {
4797 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4798 err_code |= ERR_ALERT | ERR_FATAL;
4799 goto out;
4800 }
4801 free(curproxy->header_unique_id);
4802 curproxy->header_unique_id = strdup(args[1]);
4803 }
4804
William Lallemand723b73a2012-02-08 16:37:49 +01004805 else if (strcmp(args[0], "log-format") == 0) {
4806 if (!*(args[1])) {
4807 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
4808 err_code |= ERR_ALERT | ERR_FATAL;
4809 goto out;
4810 }
William Lallemand3203ff42012-11-11 17:30:56 +01004811 if (*(args[2])) {
4812 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
4813 err_code |= ERR_ALERT | ERR_FATAL;
4814 goto out;
4815 }
Willy Tarreau196729e2012-05-31 19:30:26 +02004816
Willy Tarreau62a61232013-04-12 18:13:46 +02004817 if (curproxy->conf.logformat_string != default_http_log_format &&
4818 curproxy->conf.logformat_string != default_tcp_log_format &&
4819 curproxy->conf.logformat_string != clf_http_log_format)
4820 free(curproxy->conf.logformat_string);
4821 curproxy->conf.logformat_string = strdup(args[1]);
4822
4823 free(curproxy->conf.lfs_file);
4824 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4825 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004826
4827 /* get a chance to improve log-format error reporting by
4828 * reporting the correct line-number when possible.
4829 */
4830 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
4831 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
4832 file, linenum, curproxy->id);
4833 err_code |= ERR_WARN;
4834 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004835 }
William Lallemand723b73a2012-02-08 16:37:49 +01004836
William Lallemand0f99e342011-10-12 17:50:54 +02004837 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
4838 /* delete previous herited or defined syslog servers */
4839 struct logsrv *back;
4840
4841 if (*(args[1]) != 0) {
4842 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
4843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
4845 }
4846
William Lallemand723b73a2012-02-08 16:37:49 +01004847 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
4848 LIST_DEL(&tmplogsrv->list);
4849 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02004850 }
4851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004852 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02004853 struct logsrv *logsrv;
4854
Willy Tarreaubaaee002006-06-26 02:48:02 +02004855 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02004856 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01004857 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02004858 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01004859 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02004860 LIST_INIT(&node->list);
4861 LIST_ADDQ(&curproxy->logsrvs, &node->list);
4862 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004863 }
4864 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004865 struct sockaddr_storage *sk;
4866 int port1, port2;
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004867 int arg = 0;
4868 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02004869
4870 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02004871
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004872 /* just after the address, a length may be specified */
4873 if (strcmp(args[arg+2], "len") == 0) {
4874 len = atoi(args[arg+3]);
4875 if (len < 80 || len > 65535) {
4876 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
4877 file, linenum, args[arg+3]);
4878 err_code |= ERR_ALERT | ERR_FATAL;
4879 goto out;
4880 }
4881 logsrv->maxlen = len;
4882
4883 /* skip these two args */
4884 arg += 2;
4885 }
4886 else
4887 logsrv->maxlen = MAX_SYSLOG_LEN;
4888
4889 if (logsrv->maxlen > global.max_syslog_len) {
4890 global.max_syslog_len = logsrv->maxlen;
4891 logline = realloc(logline, global.max_syslog_len + 1);
4892 }
4893
4894 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004895 if (logsrv->facility < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004896 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02004897 err_code |= ERR_ALERT | ERR_FATAL;
4898 goto out;
4899
Willy Tarreaubaaee002006-06-26 02:48:02 +02004900 }
4901
William Lallemand0f99e342011-10-12 17:50:54 +02004902 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004903 if (*(args[arg+3])) {
4904 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004905 if (logsrv->level < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004906 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
4909
Willy Tarreaubaaee002006-06-26 02:48:02 +02004910 }
4911 }
4912
William Lallemand0f99e342011-10-12 17:50:54 +02004913 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004914 if (*(args[arg+4])) {
4915 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01004916 if (logsrv->minlvl < 0) {
Willy Tarreaudc2695c2014-06-27 18:10:07 +02004917 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02004918 err_code |= ERR_ALERT | ERR_FATAL;
4919 goto out;
4920
Willy Tarreauf7edefa2009-05-10 17:20:05 +02004921 }
4922 }
4923
Willy Tarreau902636f2013-03-10 19:44:48 +01004924 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004925 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004926 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004927 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004928 goto out;
4929 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004930
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004931 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004932
Willy Tarreau9b435bc2013-03-06 15:02:49 +01004933 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004934 if (port1 != port2) {
4935 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4936 file, linenum, args[0], args[1]);
4937 err_code |= ERR_ALERT | ERR_FATAL;
4938 goto out;
4939 }
4940
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004941 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02004942 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004943 }
William Lallemand0f99e342011-10-12 17:50:54 +02004944
4945 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004946 }
4947 else {
4948 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
4949 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004952 }
4953 }
4954 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004955 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004956 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01004957 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004958 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004959
Willy Tarreau977b8e42006-12-29 14:19:17 +01004960 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004962
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01004964 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
4965 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004968 }
Willy Tarreau368480c2009-03-01 08:27:21 +01004969
4970 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01004971 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
4972 free(curproxy->conn_src.iface_name);
4973 curproxy->conn_src.iface_name = NULL;
4974 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01004975
Willy Tarreau902636f2013-03-10 19:44:48 +01004976 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004977 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004978 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01004979 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004980 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004981 goto out;
4982 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01004983
4984 proto = protocol_by_family(sk->ss_family);
4985 if (!proto || !proto->connect) {
4986 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004987 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01004988 err_code |= ERR_ALERT | ERR_FATAL;
4989 goto out;
4990 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004991
4992 if (port1 != port2) {
4993 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
4994 file, linenum, args[0], args[1]);
4995 err_code |= ERR_ALERT | ERR_FATAL;
4996 goto out;
4997 }
4998
Willy Tarreauef9a3602012-12-08 22:29:20 +01004999 curproxy->conn_src.source_addr = *sk;
5000 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005001
5002 cur_arg = 2;
5003 while (*(args[cur_arg])) {
5004 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005005#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5006#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005007 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005008 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5009 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005010 err_code |= ERR_ALERT | ERR_FATAL;
5011 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005012 }
5013#endif
5014 if (!*args[cur_arg + 1]) {
5015 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5016 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005019 }
5020
5021 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005022 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5023 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005024 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005025 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5026 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005027 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5028 char *name, *end;
5029
5030 name = args[cur_arg+1] + 7;
5031 while (isspace(*name))
5032 name++;
5033
5034 end = name;
5035 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5036 end++;
5037
Willy Tarreauef9a3602012-12-08 22:29:20 +01005038 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5039 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5040 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5041 curproxy->conn_src.bind_hdr_len = end - name;
5042 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5043 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5044 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005045
5046 /* now look for an occurrence number */
5047 while (isspace(*end))
5048 end++;
5049 if (*end == ',') {
5050 end++;
5051 name = end;
5052 if (*end == '-')
5053 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005054 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005055 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005056 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005057 }
5058
Willy Tarreauef9a3602012-12-08 22:29:20 +01005059 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005060 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5061 " occurrences values smaller than %d.\n",
5062 file, linenum, MAX_HDR_HISTORY);
5063 err_code |= ERR_ALERT | ERR_FATAL;
5064 goto out;
5065 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005066 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005067 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005068
Willy Tarreau902636f2013-03-10 19:44:48 +01005069 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005070 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005071 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005072 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005073 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005074 goto out;
5075 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005076
5077 proto = protocol_by_family(sk->ss_family);
5078 if (!proto || !proto->connect) {
5079 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5080 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
5083 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005084
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005085 if (port1 != port2) {
5086 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5087 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
5090 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005091 curproxy->conn_src.tproxy_addr = *sk;
5092 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005093 }
5094 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005095#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005096 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005097#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005098#else /* no TPROXY support */
5099 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005100 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005103#endif
5104 cur_arg += 2;
5105 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005106 }
5107
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005108 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5109#ifdef SO_BINDTODEVICE
5110 if (!*args[cur_arg + 1]) {
5111 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5112 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005115 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005116 free(curproxy->conn_src.iface_name);
5117 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5118 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005119 global.last_checks |= LSTCHK_NETADM;
5120#else
5121 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5122 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005123 err_code |= ERR_ALERT | ERR_FATAL;
5124 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005125#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005126 cur_arg += 2;
5127 continue;
5128 }
5129 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005130 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005134 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005135 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5136 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5137 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005140 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005141 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005142 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005143 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5144 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005148
5149 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005150 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005151 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005152 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005154 }
5155 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005156 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005157 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005158 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005159 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005160 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005161 }
5162 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005163 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005164 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005165 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005166 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005168 }
5169 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005170 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005171 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005172 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005173 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005174 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 }
5176 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005177 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005178 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005179 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005180 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005181 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005182 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005183 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005184 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005185 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005186 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005187 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005188 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005189 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005190 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005191 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005192 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005193 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005194 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005195 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005196
5197 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5198 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 +01005199 }
5200 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005202 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005203 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005205 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005206
5207 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5208 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 +01005209 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005210 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005211 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005212 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005214 err_code |= ERR_ALERT | ERR_FATAL;
5215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005217
5218 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005219 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005220 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005221 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005222 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005223 }
5224 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005225 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005226 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005227 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005228 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005229 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
5231 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005232 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005233 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005234 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005235 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005237 }
5238 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005239 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005240 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005241 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005242 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
5245 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005246 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005247 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005248 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005249 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005251 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005252 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005253 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005254 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005255 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005256 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005257 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005258 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005259 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005260 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005261
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 if (curproxy == &defproxy) {
5263 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_ALERT | ERR_FATAL;
5265 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005267 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005268 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005269
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 if (*(args[1]) == 0) {
5271 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005275
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005276 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005277 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5278 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5279 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005280 err_code |= ERR_ALERT | ERR_FATAL;
5281 goto out;
5282 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005283 err_code |= warnif_cond_conflicts(cond,
5284 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5285 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005286 }
5287 else if (*args[2]) {
5288 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5289 file, linenum, args[0], args[2]);
5290 err_code |= ERR_ALERT | ERR_FATAL;
5291 goto out;
5292 }
5293
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005294 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005295 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005296 wl->s = strdup(args[1]);
5297 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005298 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005299 }
5300 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005301 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005302 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5303 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005304 err_code |= ERR_ALERT | ERR_FATAL;
5305 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005306 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005307
Willy Tarreauade5ec42010-01-28 19:33:49 +01005308 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005309 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005310 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005311 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005313 }
5314 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005315 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005316 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005317 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005318 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005319 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005320 }
5321 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005322 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005323 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005324 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005325 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005326 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005327 }
5328 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005329 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005330 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5331 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005332 err_code |= ERR_ALERT | ERR_FATAL;
5333 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005334 }
5335
Willy Tarreauade5ec42010-01-28 19:33:49 +01005336 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005337 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005338 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005339 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005341 }
5342 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005343 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005344 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005345 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005346 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005347 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005348 }
5349 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005350 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005351 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005352 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005353 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005354 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005355 }
5356 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005357 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005358
Willy Tarreaubaaee002006-06-26 02:48:02 +02005359 if (curproxy == &defproxy) {
5360 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005361 err_code |= ERR_ALERT | ERR_FATAL;
5362 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005363 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005364 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005365 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005366
Willy Tarreaubaaee002006-06-26 02:48:02 +02005367 if (*(args[1]) == 0) {
5368 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005371 }
5372
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005373 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005374 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5375 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5376 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
5379 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005380 err_code |= warnif_cond_conflicts(cond,
5381 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5382 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005383 }
5384 else if (*args[2]) {
5385 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5386 file, linenum, args[0], args[2]);
5387 err_code |= ERR_ALERT | ERR_FATAL;
5388 goto out;
5389 }
5390
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005391 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005392 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005393 wl->s = strdup(args[1]);
5394 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005395 }
5396 else if (!strcmp(args[0], "errorloc") ||
5397 !strcmp(args[0], "errorloc302") ||
5398 !strcmp(args[0], "errorloc303")) { /* error location */
5399 int errnum, errlen;
5400 char *err;
5401
Willy Tarreau977b8e42006-12-29 14:19:17 +01005402 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005403 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005404
Willy Tarreaubaaee002006-06-26 02:48:02 +02005405 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005406 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005409 }
5410
5411 errnum = atol(args[1]);
5412 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005413 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5414 err = malloc(errlen);
5415 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005416 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005417 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5418 err = malloc(errlen);
5419 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005420 }
5421
Willy Tarreau0f772532006-12-23 20:51:41 +01005422 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5423 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005424 chunk_destroy(&curproxy->errmsg[rc]);
5425 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005426 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005427 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005428 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005429
5430 if (rc >= HTTP_ERR_SIZE) {
5431 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5432 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005433 free(err);
5434 }
5435 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005436 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5437 int errnum, errlen, fd;
5438 char *err;
5439 struct stat stat;
5440
5441 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005442 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005443
5444 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005445 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005446 err_code |= ERR_ALERT | ERR_FATAL;
5447 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005448 }
5449
5450 fd = open(args[2], O_RDONLY);
5451 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5452 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5453 file, linenum, args[2], args[1]);
5454 if (fd >= 0)
5455 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005458 }
5459
Willy Tarreau27a674e2009-08-17 07:23:33 +02005460 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005461 errlen = stat.st_size;
5462 } else {
5463 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005464 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005465 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005466 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005467 }
5468
5469 err = malloc(errlen); /* malloc() must succeed during parsing */
5470 errnum = read(fd, err, errlen);
5471 if (errnum != errlen) {
5472 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5473 file, linenum, args[2], args[1]);
5474 close(fd);
5475 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005478 }
5479 close(fd);
5480
5481 errnum = atol(args[1]);
5482 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5483 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005484 chunk_destroy(&curproxy->errmsg[rc]);
5485 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005486 break;
5487 }
5488 }
5489
5490 if (rc >= HTTP_ERR_SIZE) {
5491 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5492 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005493 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005494 free(err);
5495 }
5496 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005497 else if (!strcmp(args[0], "compression")) {
5498 struct comp *comp;
5499 if (curproxy->comp == NULL) {
5500 comp = calloc(1, sizeof(struct comp));
5501 curproxy->comp = comp;
5502 } else {
5503 comp = curproxy->comp;
5504 }
5505
5506 if (!strcmp(args[1], "algo")) {
5507 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005508 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005509
William Lallemand82fe75c2012-10-23 10:25:10 +02005510 cur_arg = 2;
5511 if (!*args[cur_arg]) {
5512 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5513 file, linenum, args[0]);
5514 err_code |= ERR_ALERT | ERR_FATAL;
5515 goto out;
5516 }
5517 while (*(args[cur_arg])) {
5518 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5519 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5520 file, linenum, args[0], args[cur_arg]);
5521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
5523 }
William Lallemand552df672012-11-07 13:21:47 +01005524 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5525 curproxy->comp->algos->end(&ctx);
5526 } else {
5527 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5528 file, linenum, args[0], args[cur_arg]);
5529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
5531 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005532 cur_arg ++;
5533 continue;
5534 }
5535 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005536 else if (!strcmp(args[1], "offload")) {
5537 comp->offload = 1;
5538 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005539 else if (!strcmp(args[1], "type")) {
5540 int cur_arg;
5541 cur_arg = 2;
5542 if (!*args[cur_arg]) {
5543 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5544 file, linenum, args[0]);
5545 err_code |= ERR_ALERT | ERR_FATAL;
5546 goto out;
5547 }
5548 while (*(args[cur_arg])) {
5549 comp_append_type(comp, args[cur_arg]);
5550 cur_arg ++;
5551 continue;
5552 }
5553 }
5554 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005555 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005556 file, linenum, args[0]);
5557 err_code |= ERR_ALERT | ERR_FATAL;
5558 goto out;
5559 }
5560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005561 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005562 struct cfg_kw_list *kwl;
5563 int index;
5564
5565 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5566 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5567 if (kwl->kw[index].section != CFG_LISTEN)
5568 continue;
5569 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5570 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005571 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005572 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005573 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005574 err_code |= ERR_ALERT | ERR_FATAL;
5575 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005576 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005577 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005578 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005579 err_code |= ERR_WARN;
5580 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005581 }
Willy Tarreau93893792009-07-23 13:19:11 +02005582 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005583 }
5584 }
5585 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005586
Willy Tarreau6daf3432008-01-22 16:44:08 +01005587 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005588 err_code |= ERR_ALERT | ERR_FATAL;
5589 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 }
Willy Tarreau93893792009-07-23 13:19:11 +02005591 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005592 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005593 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594}
5595
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005596int
5597cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5598{
5599
5600 int err_code = 0;
5601 const char *err;
5602
5603 if (!strcmp(args[0], "userlist")) { /* new userlist */
5604 struct userlist *newul;
5605
5606 if (!*args[1]) {
5607 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5608 file, linenum, args[0]);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
5612
5613 err = invalid_char(args[1]);
5614 if (err) {
5615 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5616 file, linenum, *err, args[0], args[1]);
5617 err_code |= ERR_ALERT | ERR_FATAL;
5618 goto out;
5619 }
5620
5621 for (newul = userlist; newul; newul = newul->next)
5622 if (!strcmp(newul->name, args[1])) {
5623 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5624 file, linenum, args[1]);
5625 err_code |= ERR_WARN;
5626 goto out;
5627 }
5628
5629 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5630 if (!newul) {
5631 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5632 err_code |= ERR_ALERT | ERR_ABORT;
5633 goto out;
5634 }
5635
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005636 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005637 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005638 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5639 err_code |= ERR_ALERT | ERR_ABORT;
5640 goto out;
5641 }
5642
5643 newul->next = userlist;
5644 userlist = newul;
5645
5646 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005647 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005648 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005649 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005650
5651 if (!*args[1]) {
5652 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5653 file, linenum, args[0]);
5654 err_code |= ERR_ALERT | ERR_FATAL;
5655 goto out;
5656 }
5657
5658 err = invalid_char(args[1]);
5659 if (err) {
5660 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5661 file, linenum, *err, args[0], args[1]);
5662 err_code |= ERR_ALERT | ERR_FATAL;
5663 goto out;
5664 }
5665
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005666 for (ag = userlist->groups; ag; ag = ag->next)
5667 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005668 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
5669 file, linenum, args[1], userlist->name);
5670 err_code |= ERR_ALERT;
5671 goto out;
5672 }
5673
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005674 ag = calloc(1, sizeof(*ag));
5675 if (!ag) {
5676 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5677 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005678 goto out;
5679 }
5680
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005681 ag->name = strdup(args[1]);
5682 if (!ag) {
5683 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5684 err_code |= ERR_ALERT | ERR_ABORT;
5685 goto out;
5686 }
5687
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005688 cur_arg = 2;
5689
5690 while (*args[cur_arg]) {
5691 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005692 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005693 cur_arg += 2;
5694 continue;
5695 } else {
5696 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
5697 file, linenum, args[0]);
5698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
5701 }
5702
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005703 ag->next = userlist->groups;
5704 userlist->groups = ag;
5705
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005706 } else if (!strcmp(args[0], "user")) { /* new user */
5707 struct auth_users *newuser;
5708 int cur_arg;
5709
5710 if (!*args[1]) {
5711 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5712 file, linenum, args[0]);
5713 err_code |= ERR_ALERT | ERR_FATAL;
5714 goto out;
5715 }
5716
5717 for (newuser = userlist->users; newuser; newuser = newuser->next)
5718 if (!strcmp(newuser->user, args[1])) {
5719 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
5720 file, linenum, args[1], userlist->name);
5721 err_code |= ERR_ALERT;
5722 goto out;
5723 }
5724
5725 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
5726 if (!newuser) {
5727 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5728 err_code |= ERR_ALERT | ERR_ABORT;
5729 goto out;
5730 }
5731
5732 newuser->user = strdup(args[1]);
5733
5734 newuser->next = userlist->users;
5735 userlist->users = newuser;
5736
5737 cur_arg = 2;
5738
5739 while (*args[cur_arg]) {
5740 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté2c8d7002014-08-29 20:20:02 +02005741#ifdef CONFIG_HAP_CRYPT
5742 if (!crypt("", args[cur_arg + 1])) {
5743 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
5744 file, linenum, newuser->user);
5745 err_code |= ERR_ALERT | ERR_FATAL;
5746 goto out;
5747 }
5748#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005749 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
5750 file, linenum);
5751 err_code |= ERR_ALERT;
5752#endif
5753 newuser->pass = strdup(args[cur_arg + 1]);
5754 cur_arg += 2;
5755 continue;
5756 } else if (!strcmp(args[cur_arg], "insecure-password")) {
5757 newuser->pass = strdup(args[cur_arg + 1]);
5758 newuser->flags |= AU_O_INSECURE;
5759 cur_arg += 2;
5760 continue;
5761 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005762 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005763 cur_arg += 2;
5764 continue;
5765 } else {
5766 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
5767 file, linenum, args[0]);
5768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
5770 }
5771 }
5772 } else {
5773 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
5774 err_code |= ERR_ALERT | ERR_FATAL;
5775 }
5776
5777out:
5778 return err_code;
5779}
Willy Tarreaubaaee002006-06-26 02:48:02 +02005780
5781/*
5782 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02005783 * Returns the error code, 0 if OK, or any combination of :
5784 * - ERR_ABORT: must abort ASAP
5785 * - ERR_FATAL: we can continue parsing but not start the service
5786 * - ERR_WARN: a warning has been emitted
5787 * - ERR_ALERT: an alert has been emitted
5788 * Only the two first ones can stop processing, the two others are just
5789 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02005790 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02005791int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005793 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02005794 FILE *f;
5795 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02005796 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005797 struct cfg_section *cs = NULL;
5798 struct cfg_section *ics;
5799
5800 /* Register internal sections */
5801 if (!cfg_register_section("listen", cfg_parse_listen) ||
5802 !cfg_register_section("frontend", cfg_parse_listen) ||
5803 !cfg_register_section("backend", cfg_parse_listen) ||
5804 !cfg_register_section("ruleset", cfg_parse_listen) ||
5805 !cfg_register_section("defaults", cfg_parse_listen) ||
5806 !cfg_register_section("global", cfg_parse_global) ||
5807 !cfg_register_section("userlist", cfg_parse_users) ||
5808 !cfg_register_section("peers", cfg_parse_peers))
5809 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005810
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 if ((f=fopen(file,"r")) == NULL)
5812 return -1;
5813
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005814 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02005815 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005816 char *end;
5817 char *args[MAX_LINE_ARGS + 1];
5818 char *line = thisline;
5819
Willy Tarreaubaaee002006-06-26 02:48:02 +02005820 linenum++;
5821
5822 end = line + strlen(line);
5823
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005824 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
5825 /* Check if we reached the limit and the last char is not \n.
5826 * Watch out for the last line without the terminating '\n'!
5827 */
5828 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02005829 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02005830 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005831 }
5832
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005834 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835 line++;
5836
5837 arg = 0;
5838 args[arg] = line;
5839
5840 while (*line && arg < MAX_LINE_ARGS) {
5841 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
5842 * C equivalent value. Other combinations left unchanged (eg: \1).
5843 */
5844 if (*line == '\\') {
5845 int skip = 0;
5846 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
5847 *line = line[1];
5848 skip = 1;
5849 }
5850 else if (line[1] == 'r') {
5851 *line = '\r';
5852 skip = 1;
5853 }
5854 else if (line[1] == 'n') {
5855 *line = '\n';
5856 skip = 1;
5857 }
5858 else if (line[1] == 't') {
5859 *line = '\t';
5860 skip = 1;
5861 }
5862 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01005863 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 unsigned char hex1, hex2;
5865 hex1 = toupper(line[2]) - '0';
5866 hex2 = toupper(line[3]) - '0';
5867 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
5868 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
5869 *line = (hex1<<4) + hex2;
5870 skip = 3;
5871 }
5872 else {
5873 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005874 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005875 }
5876 }
5877 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01005878 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005879 end -= skip;
5880 }
5881 line++;
5882 }
5883 else if (*line == '#' || *line == '\n' || *line == '\r') {
5884 /* end of string, end of loop */
5885 *line = 0;
5886 break;
5887 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005888 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01005890 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02005891 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02005892 line++;
5893 args[++arg] = line;
5894 }
5895 else {
5896 line++;
5897 }
5898 }
5899
5900 /* empty line */
5901 if (!**args)
5902 continue;
5903
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005904 if (*line) {
5905 /* we had to stop due to too many args.
5906 * Let's terminate the string, print the offending part then cut the
5907 * last arg.
5908 */
5909 while (*line && *line != '#' && *line != '\n' && *line != '\r')
5910 line++;
5911 *line = '\0';
5912
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01005913 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01005914 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01005915 err_code |= ERR_ALERT | ERR_FATAL;
5916 args[arg] = line;
5917 }
5918
Willy Tarreau540abe42007-05-02 20:50:16 +02005919 /* zero out remaining args and ensure that at least one entry
5920 * is zeroed out.
5921 */
5922 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005923 args[arg] = line;
5924 }
5925
Willy Tarreau3842f002009-06-14 11:39:52 +02005926 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005927 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005928 char *tmp;
5929
Willy Tarreau3842f002009-06-14 11:39:52 +02005930 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02005931 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005932 for (arg=0; *args[arg+1]; arg++)
5933 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02005934 *tmp = '\0'; // fix the next arg to \0
5935 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005936 }
Willy Tarreau3842f002009-06-14 11:39:52 +02005937 else if (!strcmp(args[0], "default")) {
5938 kwm = KWM_DEF;
5939 for (arg=0; *args[arg+1]; arg++)
5940 args[arg] = args[arg+1]; // shift args after inversion
5941 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005942
William Lallemand0f99e342011-10-12 17:50:54 +02005943 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
5944 strcmp(args[0], "log") != 0) {
5945 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02005946 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01005947 }
5948
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005949 /* detect section start */
5950 list_for_each_entry(ics, &sections, list) {
5951 if (strcmp(args[0], ics->section_name) == 0) {
5952 cursection = ics->section_name;
5953 cs = ics;
5954 break;
5955 }
Emeric Brun32da3c42010-09-23 18:39:19 +02005956 }
5957
Willy Tarreaubaaee002006-06-26 02:48:02 +02005958 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01005959 if (cs)
5960 err_code |= cs->section_parser(file, linenum, args, kwm);
5961 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005962 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02005963 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005964 }
Willy Tarreau058e9072009-07-20 09:30:05 +02005965
5966 if (err_code & ERR_ABORT)
5967 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005968 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01005969 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005970 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02005971 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02005972}
5973
Willy Tarreau5436afc2014-09-16 12:17:36 +02005974/* This function propagates processes from frontend <from> to backend <to> so
5975 * that it is always guaranteed that a backend pointed to by a frontend is
5976 * bound to all of its processes. After that, if the target is a "listen"
5977 * instance, the function recursively descends the target's own targets along
5978 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
5979 * checked first to ensure that <to> is already bound to all processes of
5980 * <from>, there is no risk of looping and we ensure to follow the shortest
5981 * path to the destination.
5982 *
5983 * It is possible to set <to> to NULL for the first call so that the function
5984 * takes care of visiting the initial frontend in <from>.
5985 *
5986 * It is important to note that the function relies on the fact that all names
5987 * have already been resolved.
5988 */
5989void propagate_processes(struct proxy *from, struct proxy *to)
5990{
5991 struct switching_rule *rule;
5992 struct hdr_exp *exp;
5993
5994 if (to) {
5995 /* check whether we need to go down */
5996 if (from->bind_proc &&
5997 (from->bind_proc & to->bind_proc) == from->bind_proc)
5998 return;
5999
6000 if (!from->bind_proc && !to->bind_proc)
6001 return;
6002
6003 to->bind_proc = from->bind_proc ?
6004 (to->bind_proc | from->bind_proc) : 0;
6005
6006 /* now propagate down */
6007 from = to;
6008 }
6009
Willy Tarreau7110f382014-12-18 13:56:26 +01006010 if (!(from->cap & PR_CAP_FE))
Willy Tarreau5436afc2014-09-16 12:17:36 +02006011 return;
6012
Willy Tarreaued061c02014-12-18 14:00:43 +01006013 if (from->state == PR_STSTOPPED)
6014 return;
6015
Willy Tarreau5436afc2014-09-16 12:17:36 +02006016 /* default_backend */
6017 if (from->defbe.be)
6018 propagate_processes(from, from->defbe.be);
6019
6020 /* use_backend */
6021 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bontéc8d57de2014-10-02 19:56:25 +02006022 if (rule->dynamic)
6023 continue;
Willy Tarreau5436afc2014-09-16 12:17:36 +02006024 to = rule->be.backend;
6025 propagate_processes(from, to);
6026 }
6027
6028 /* reqsetbe */
6029 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6030 if (exp->action != ACT_SETBE)
6031 continue;
6032 to = (struct proxy *)exp->replace;
6033 propagate_processes(from, to);
6034 }
6035}
6036
Willy Tarreaubb925012009-07-23 13:36:36 +02006037/*
6038 * Returns the error code, 0 if OK, or any combination of :
6039 * - ERR_ABORT: must abort ASAP
6040 * - ERR_FATAL: we can continue parsing but not start the service
6041 * - ERR_WARN: a warning has been emitted
6042 * - ERR_ALERT: an alert has been emitted
6043 * Only the two first ones can stop processing, the two others are just
6044 * indicators.
6045 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006046int check_config_validity()
6047{
6048 int cfgerr = 0;
6049 struct proxy *curproxy = NULL;
6050 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006051 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006052 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006053 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006055 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006056 /*
6057 * Now, check for the integrity of all that we have collected.
6058 */
6059
6060 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006061 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062
Willy Tarreau193b8c62012-11-22 00:17:38 +01006063 if (!global.tune.max_http_hdr)
6064 global.tune.max_http_hdr = MAX_HTTP_HDR;
6065
6066 if (!global.tune.cookie_len)
6067 global.tune.cookie_len = CAPTURE_LEN;
6068
6069 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6070
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006071 /* Post initialisation of the users and groups lists. */
6072 err_code = userlist_postinit();
6073 if (err_code != ERR_NONE)
6074 goto out;
6075
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006076 /* first, we will invert the proxy list order */
6077 curproxy = NULL;
6078 while (proxy) {
6079 struct proxy *next;
6080
6081 next = proxy->next;
6082 proxy->next = curproxy;
6083 curproxy = proxy;
6084 if (!next)
6085 break;
6086 proxy = next;
6087 }
6088
Willy Tarreau91b00c22014-09-16 13:41:21 +02006089 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006090 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006091 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006092 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006093 struct tcp_rule *trule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006094 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006095 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006096
Willy Tarreau050536d2012-10-04 08:47:34 +02006097 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006098 /* proxy ID not set, use automatic numbering with first
6099 * spare entry starting with next_pxid.
6100 */
6101 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6102 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6103 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006104 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006105 next_pxid++;
6106
Willy Tarreau55ea7572007-06-17 19:56:27 +02006107
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006109 /* ensure we don't keep listeners uselessly bound */
6110 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006111 continue;
6112 }
6113
Willy Tarreau102df612014-05-07 23:56:38 +02006114 /* Check multi-process mode compatibility for the current proxy */
6115
6116 if (curproxy->bind_proc) {
6117 /* an explicit bind-process was specified, let's check how many
6118 * processes remain.
6119 */
6120 nbproc = popcount(curproxy->bind_proc);
6121
6122 curproxy->bind_proc &= nbits(global.nbproc);
6123 if (!curproxy->bind_proc && nbproc == 1) {
6124 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);
6125 curproxy->bind_proc = 1;
6126 }
6127 else if (!curproxy->bind_proc && nbproc > 1) {
6128 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);
6129 curproxy->bind_proc = 0;
6130 }
6131 }
6132
Willy Tarreau3d209582014-05-09 17:06:11 +02006133 /* check and reduce the bind-proc of each listener */
6134 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6135 unsigned long mask;
6136
6137 if (!bind_conf->bind_proc)
6138 continue;
6139
6140 mask = nbits(global.nbproc);
6141 if (curproxy->bind_proc)
6142 mask &= curproxy->bind_proc;
6143 /* mask cannot be null here thanks to the previous checks */
6144
6145 nbproc = popcount(bind_conf->bind_proc);
6146 bind_conf->bind_proc &= mask;
6147
6148 if (!bind_conf->bind_proc && nbproc == 1) {
6149 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",
6150 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6151 bind_conf->bind_proc = mask & ~(mask - 1);
6152 }
6153 else if (!bind_conf->bind_proc && nbproc > 1) {
6154 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",
6155 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6156 bind_conf->bind_proc = 0;
6157 }
6158 }
6159
Willy Tarreau102df612014-05-07 23:56:38 +02006160 if (global.nbproc > 1 && curproxy->table.peers.name) {
6161 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6162 curproxy->id);
6163 cfgerr++;
6164 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006165
Willy Tarreauff01a212009-03-15 13:46:16 +01006166 switch (curproxy->mode) {
6167 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006168 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006169 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006170 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6171 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006172 cfgerr++;
6173 }
6174
6175 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006176 Warning("config : servers will be ignored for %s '%s'.\n",
6177 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006178 break;
6179
6180 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006181 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006182 break;
6183
6184 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006185 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006186 break;
6187 }
6188
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006189 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006190 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006191 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006192 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6193 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006194 cfgerr++;
6195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006196#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006197 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006198 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6199 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006200 cfgerr++;
6201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006203 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006204 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6205 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006206 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006207 }
6208 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006209 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006210 /* If no LB algo is set in a backend, and we're not in
6211 * transparent mode, dispatch mode nor proxy mode, we
6212 * want to use balance roundrobin by default.
6213 */
6214 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6215 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 }
6217 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006218
Willy Tarreau1620ec32011-08-06 17:05:02 +02006219 if (curproxy->options & PR_O_DISPATCH)
6220 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6221 else if (curproxy->options & PR_O_HTTP_PROXY)
6222 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6223 else if (curproxy->options & PR_O_TRANSP)
6224 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006225
Willy Tarreau1620ec32011-08-06 17:05:02 +02006226 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6227 if (curproxy->options & PR_O_DISABLE404) {
6228 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6229 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6230 err_code |= ERR_WARN;
6231 curproxy->options &= ~PR_O_DISABLE404;
6232 }
6233 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6234 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6235 "send-state", proxy_type_str(curproxy), curproxy->id);
6236 err_code |= ERR_WARN;
6237 curproxy->options &= ~PR_O2_CHK_SNDST;
6238 }
Willy Tarreauef781042010-01-27 11:53:01 +01006239 }
6240
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006241 /* if a default backend was specified, let's find it */
6242 if (curproxy->defbe.name) {
6243 struct proxy *target;
6244
Alex Williams96532db2009-11-01 21:27:13 -05006245 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006246 if (!target) {
6247 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6248 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006249 cfgerr++;
6250 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006251 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6252 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006253 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006254 } else {
6255 free(curproxy->defbe.name);
6256 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006257
6258 /* Emit a warning if this proxy also has some servers */
6259 if (curproxy->srv) {
6260 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6261 curproxy->id);
6262 err_code |= ERR_WARN;
6263 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264 }
6265 }
6266
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006267 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006268 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6269 /* map jump target for ACT_SETBE in req_rep chain */
6270 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006271 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006272 struct proxy *target;
6273
Willy Tarreaua496b602006-12-17 23:15:24 +01006274 if (exp->action != ACT_SETBE)
6275 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006276
Alex Williams96532db2009-11-01 21:27:13 -05006277 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006278 if (!target) {
6279 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6280 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006281 cfgerr++;
6282 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006283 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6284 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006285 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006286 } else {
6287 free((void *)exp->replace);
6288 exp->replace = (const char *)target;
6289 }
6290 }
6291 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006292
6293 /* find the target proxy for 'use_backend' rules */
6294 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006295 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006296 struct logformat_node *node;
6297 char *pxname;
6298
6299 /* Try to parse the string as a log format expression. If the result
6300 * of the parsing is only one entry containing a simple string, then
6301 * it's a standard string corresponding to a static rule, thus the
6302 * parsing is cancelled and be.name is restored to be resolved.
6303 */
6304 pxname = rule->be.name;
6305 LIST_INIT(&rule->be.expr);
6306 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6307 curproxy->conf.args.file, curproxy->conf.args.line);
6308 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6309
6310 if (!LIST_ISEMPTY(&rule->be.expr)) {
6311 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6312 rule->dynamic = 1;
6313 free(pxname);
6314 continue;
6315 }
6316 /* simple string: free the expression and fall back to static rule */
6317 free(node->arg);
6318 free(node);
6319 }
6320
6321 rule->dynamic = 0;
6322 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006323
Alex Williams96532db2009-11-01 21:27:13 -05006324 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006325
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006326 if (!target) {
6327 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6328 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006329 cfgerr++;
6330 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006331 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6332 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006333 cfgerr++;
6334 } else {
6335 free((void *)rule->be.name);
6336 rule->be.backend = target;
6337 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006338 }
6339
Willy Tarreau5436afc2014-09-16 12:17:36 +02006340 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006341 list_for_each_entry(srule, &curproxy->server_rules, list) {
6342 struct server *target = findserver(curproxy, srule->srv.name);
6343
6344 if (!target) {
6345 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6346 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6347 cfgerr++;
6348 continue;
6349 }
6350 free((void *)srule->srv.name);
6351 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006352 }
6353
Emeric Brunb982a3d2010-01-04 15:45:53 +01006354 /* find the target table for 'stick' rules */
6355 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6356 struct proxy *target;
6357
Emeric Brun1d33b292010-01-04 15:47:17 +01006358 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6359 if (mrule->flags & STK_IS_STORE)
6360 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6361
Emeric Brunb982a3d2010-01-04 15:45:53 +01006362 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006363 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006364 else
6365 target = curproxy;
6366
6367 if (!target) {
6368 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6369 curproxy->id, mrule->table.name);
6370 cfgerr++;
6371 }
6372 else if (target->table.size == 0) {
6373 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6374 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6375 cfgerr++;
6376 }
Willy Tarreau12785782012-04-27 21:37:17 +02006377 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6378 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006379 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6380 cfgerr++;
6381 }
6382 else {
6383 free((void *)mrule->table.name);
6384 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006385 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006386 }
6387 }
6388
6389 /* find the target table for 'store response' rules */
6390 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6391 struct proxy *target;
6392
Emeric Brun1d33b292010-01-04 15:47:17 +01006393 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 store 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
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006422 /* find the target table for 'tcp-request' layer 4 rules */
6423 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6424 struct proxy *target;
6425
Willy Tarreaub4c84932013-07-23 19:15:30 +02006426 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006427 continue;
6428
6429 if (trule->act_prm.trk_ctr.table.n)
6430 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6431 else
6432 target = curproxy;
6433
6434 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006435 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6436 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006437 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006438 cfgerr++;
6439 }
6440 else if (target->table.size == 0) {
6441 Alert("Proxy '%s': table '%s' used but not configured.\n",
6442 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6443 cfgerr++;
6444 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006445 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6446 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6447 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 +01006448 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006449 cfgerr++;
6450 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006451 else {
6452 free(trule->act_prm.trk_ctr.table.n);
6453 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006454 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006455 * to pass a list of counters to track and allocate them right here using
6456 * stktable_alloc_data_type().
6457 */
6458 }
6459 }
6460
Willy Tarreaud1f96522010-08-03 19:34:32 +02006461 /* find the target table for 'tcp-request' layer 6 rules */
6462 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6463 struct proxy *target;
6464
Willy Tarreaub4c84932013-07-23 19:15:30 +02006465 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006466 continue;
6467
6468 if (trule->act_prm.trk_ctr.table.n)
6469 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6470 else
6471 target = curproxy;
6472
6473 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006474 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6475 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006476 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006477 cfgerr++;
6478 }
6479 else if (target->table.size == 0) {
6480 Alert("Proxy '%s': table '%s' used but not configured.\n",
6481 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6482 cfgerr++;
6483 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006484 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6485 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6486 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 +01006487 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006488 cfgerr++;
6489 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006490 else {
6491 free(trule->act_prm.trk_ctr.table.n);
6492 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006493 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006494 * to pass a list of counters to track and allocate them right here using
6495 * stktable_alloc_data_type().
6496 */
6497 }
6498 }
6499
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006500 /* move any "block" rules at the beginning of the http-request rules */
6501 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6502 /* insert block_rules into http_req_rules at the beginning */
6503 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6504 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6505 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6506 curproxy->http_req_rules.n = curproxy->block_rules.n;
6507 LIST_INIT(&curproxy->block_rules);
6508 }
6509
Emeric Brun32da3c42010-09-23 18:39:19 +02006510 if (curproxy->table.peers.name) {
6511 struct peers *curpeers = peers;
6512
6513 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6514 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6515 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006516 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006517 break;
6518 }
6519 }
6520
6521 if (!curpeers) {
6522 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6523 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006524 free((void *)curproxy->table.peers.name);
6525 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006526 cfgerr++;
6527 }
6528 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006529 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6530 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006531 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006532 cfgerr++;
6533 }
6534 }
6535
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006536 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01006537 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006538 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
6539 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
6540 "proxy", curproxy->id);
6541 cfgerr++;
6542 goto out_uri_auth_compat;
6543 }
6544
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006545 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006546 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01006547 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01006548 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006549
Willy Tarreau95fa4692010-02-01 13:05:50 +01006550 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
6551 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006552
6553 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006554 uri_auth_compat_req[i++] = "realm";
6555 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
6556 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006557
Willy Tarreau95fa4692010-02-01 13:05:50 +01006558 uri_auth_compat_req[i++] = "unless";
6559 uri_auth_compat_req[i++] = "{";
6560 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
6561 uri_auth_compat_req[i++] = "}";
6562 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006563
Willy Tarreauff011f22011-01-06 17:51:27 +01006564 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
6565 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01006566 cfgerr++;
6567 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006568 }
6569
Willy Tarreauff011f22011-01-06 17:51:27 +01006570 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01006571
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006572 if (curproxy->uri_auth->auth_realm) {
6573 free(curproxy->uri_auth->auth_realm);
6574 curproxy->uri_auth->auth_realm = NULL;
6575 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01006576
6577 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01006578 }
6579out_uri_auth_compat:
6580
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006581 /* compile the log format */
6582 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02006583 if (curproxy->conf.logformat_string != default_http_log_format &&
6584 curproxy->conf.logformat_string != default_tcp_log_format &&
6585 curproxy->conf.logformat_string != clf_http_log_format)
6586 free(curproxy->conf.logformat_string);
6587 curproxy->conf.logformat_string = NULL;
6588 free(curproxy->conf.lfs_file);
6589 curproxy->conf.lfs_file = NULL;
6590 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006591 }
6592
Willy Tarreau62a61232013-04-12 18:13:46 +02006593 if (curproxy->conf.logformat_string) {
6594 curproxy->conf.args.ctx = ARGC_LOG;
6595 curproxy->conf.args.file = curproxy->conf.lfs_file;
6596 curproxy->conf.args.line = curproxy->conf.lfs_line;
6597 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006598 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006599 curproxy->conf.args.file = NULL;
6600 curproxy->conf.args.line = 0;
6601 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006602
Willy Tarreau62a61232013-04-12 18:13:46 +02006603 if (curproxy->conf.uniqueid_format_string) {
6604 curproxy->conf.args.ctx = ARGC_UIF;
6605 curproxy->conf.args.file = curproxy->conf.uif_file;
6606 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01006607 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbach543b9782014-12-18 15:44:58 +08006608 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01006609 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02006610 curproxy->conf.args.file = NULL;
6611 curproxy->conf.args.line = 0;
6612 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006613
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006614 /* only now we can check if some args remain unresolved.
6615 * This must be done after the users and groups resolution.
6616 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006617 cfgerr += smp_resolve_args(curproxy);
6618 if (!cfgerr)
6619 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01006620
Willy Tarreau2738a142006-07-08 17:28:09 +02006621 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006622 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02006623 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02006624 (!curproxy->timeout.connect ||
6625 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006626 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02006627 " | While not properly invalid, you will certainly encounter various problems\n"
6628 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01006629 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006630 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006631 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02006632 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02006633
Willy Tarreau1fa31262007-12-03 00:36:16 +01006634 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
6635 * We must still support older configurations, so let's find out whether those
6636 * parameters have been set or must be copied from contimeouts.
6637 */
6638 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006639 if (!curproxy->timeout.tarpit ||
6640 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006641 /* tarpit timeout not set. We search in the following order:
6642 * default.tarpit, curr.connect, default.connect.
6643 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006644 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006645 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006646 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006647 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006648 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006649 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006650 }
6651 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006652 (!curproxy->timeout.queue ||
6653 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01006654 /* queue timeout not set. We search in the following order:
6655 * default.queue, curr.connect, default.connect.
6656 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006657 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01006658 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006659 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006660 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02006661 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01006662 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01006663 }
6664 }
6665
Willy Tarreau1620ec32011-08-06 17:05:02 +02006666 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01006667 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
6668 curproxy->check_req = (char *)malloc(curproxy->check_len);
6669 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02006670 }
6671
Willy Tarreau215663d2014-06-13 18:30:23 +02006672 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
6673 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
6674 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
6675 proxy_type_str(curproxy), curproxy->id);
6676 err_code |= ERR_WARN;
6677 }
6678
Willy Tarreau193b8c62012-11-22 00:17:38 +01006679 /* ensure that cookie capture length is not too large */
6680 if (curproxy->capture_len >= global.tune.cookie_len) {
6681 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
6682 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
6683 err_code |= ERR_WARN;
6684 curproxy->capture_len = global.tune.cookie_len - 1;
6685 }
6686
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006687 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01006688 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006689 curproxy->req_cap_pool = create_pool("ptrcap",
6690 curproxy->nb_req_cap * sizeof(char *),
6691 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006692 }
6693
6694 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02006695 curproxy->rsp_cap_pool = create_pool("ptrcap",
6696 curproxy->nb_rsp_cap * sizeof(char *),
6697 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01006698 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02006699
Willy Tarreaubaaee002006-06-26 02:48:02 +02006700 /* first, we will invert the servers list order */
6701 newsrv = NULL;
6702 while (curproxy->srv) {
6703 struct server *next;
6704
6705 next = curproxy->srv->next;
6706 curproxy->srv->next = newsrv;
6707 newsrv = curproxy->srv;
6708 if (!next)
6709 break;
6710 curproxy->srv = next;
6711 }
6712
Willy Tarreau17edc812014-01-03 12:14:34 +01006713 /* Check that no server name conflicts. This causes trouble in the stats.
6714 * We only emit a warning for the first conflict affecting each server,
6715 * in order to avoid combinatory explosion if all servers have the same
6716 * name. We do that only for servers which do not have an explicit ID,
6717 * because these IDs were made also for distinguishing them and we don't
6718 * want to annoy people who correctly manage them.
6719 */
6720 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
6721 struct server *other_srv;
6722
6723 if (newsrv->puid)
6724 continue;
6725
6726 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
6727 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
6728 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
6729 newsrv->conf.file, newsrv->conf.line,
6730 proxy_type_str(curproxy), curproxy->id,
6731 newsrv->id, other_srv->conf.line);
6732 break;
6733 }
6734 }
6735 }
6736
Willy Tarreaudd701652010-05-25 23:03:02 +02006737 /* assign automatic UIDs to servers which don't have one yet */
6738 next_id = 1;
6739 newsrv = curproxy->srv;
6740 while (newsrv != NULL) {
6741 if (!newsrv->puid) {
6742 /* server ID not set, use automatic numbering with first
6743 * spare entry starting with next_svid.
6744 */
6745 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
6746 newsrv->conf.id.key = newsrv->puid = next_id;
6747 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
6748 }
6749 next_id++;
6750 newsrv = newsrv->next;
6751 }
6752
Willy Tarreau20697042007-11-15 23:26:18 +01006753 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01006754 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006755
Willy Tarreau62c3be22012-01-20 13:12:32 +01006756 /*
6757 * If this server supports a maxconn parameter, it needs a dedicated
6758 * tasks to fill the emptied slots when a connection leaves.
6759 * Also, resolve deferred tracking dependency if needed.
6760 */
6761 newsrv = curproxy->srv;
6762 while (newsrv != NULL) {
6763 if (newsrv->minconn > newsrv->maxconn) {
6764 /* Only 'minconn' was specified, or it was higher than or equal
6765 * to 'maxconn'. Let's turn this into maxconn and clean it, as
6766 * this will avoid further useless expensive computations.
6767 */
6768 newsrv->maxconn = newsrv->minconn;
6769 } else if (newsrv->maxconn && !newsrv->minconn) {
6770 /* minconn was not specified, so we set it to maxconn */
6771 newsrv->minconn = newsrv->maxconn;
6772 }
6773
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006774#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02006775 if (newsrv->use_ssl || newsrv->check.use_ssl)
6776 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02006777#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02006778
Willy Tarreau2f075e92013-12-03 11:11:34 +01006779 /* set the check type on the server */
6780 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
6781
Willy Tarreau62c3be22012-01-20 13:12:32 +01006782 if (newsrv->trackit) {
6783 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02006784 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006785 char *pname, *sname;
6786
6787 pname = newsrv->trackit;
6788 sname = strrchr(pname, '/');
6789
6790 if (sname)
6791 *sname++ = '\0';
6792 else {
6793 sname = pname;
6794 pname = NULL;
6795 }
6796
6797 if (pname) {
6798 px = findproxy(pname, PR_CAP_BE);
6799 if (!px) {
6800 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
6801 proxy_type_str(curproxy), curproxy->id,
6802 newsrv->id, pname);
6803 cfgerr++;
6804 goto next_srv;
6805 }
6806 } else
6807 px = curproxy;
6808
6809 srv = findserver(px, sname);
6810 if (!srv) {
6811 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
6812 proxy_type_str(curproxy), curproxy->id,
6813 newsrv->id, sname);
6814 cfgerr++;
6815 goto next_srv;
6816 }
6817
Willy Tarreau32091232014-05-16 13:52:00 +02006818 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
6819 !(srv->agent.state & CHK_ST_CONFIGURED) &&
6820 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01006821 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02006822 "tracking as it does not have any check nor agent enabled.\n",
6823 proxy_type_str(curproxy), curproxy->id,
6824 newsrv->id, px->id, srv->id);
6825 cfgerr++;
6826 goto next_srv;
6827 }
6828
6829 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
6830
6831 if (loop) {
6832 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
6833 "belongs to a tracking chain looping back to %s/%s.\n",
6834 proxy_type_str(curproxy), curproxy->id,
6835 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01006836 cfgerr++;
6837 goto next_srv;
6838 }
6839
6840 if (curproxy != px &&
6841 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
6842 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
6843 "tracking: disable-on-404 option inconsistency.\n",
6844 proxy_type_str(curproxy), curproxy->id,
6845 newsrv->id, px->id, srv->id);
6846 cfgerr++;
6847 goto next_srv;
6848 }
6849
6850 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02006851 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02006852 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02006853 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09006854 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006855 }
6856
6857 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01006858 newsrv->tracknext = srv->trackers;
6859 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01006860
6861 free(newsrv->trackit);
6862 newsrv->trackit = NULL;
6863 }
6864 next_srv:
6865 newsrv = newsrv->next;
6866 }
6867
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006868 /* We have to initialize the server lookup mechanism depending
6869 * on what LB algorithm was choosen.
6870 */
6871
6872 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
6873 switch (curproxy->lbprm.algo & BE_LB_KIND) {
6874 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02006875 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
6876 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6877 init_server_map(curproxy);
6878 } else {
6879 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
6880 fwrr_init_server_groups(curproxy);
6881 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006882 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006883
Willy Tarreau3ebb1162012-02-13 16:57:44 +01006884 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01006885 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
6886 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
6887 fwlc_init_server_tree(curproxy);
6888 } else {
6889 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
6890 fas_init_server_tree(curproxy);
6891 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006892 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006893
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006894 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02006895 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
6896 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
6897 chash_init_server_tree(curproxy);
6898 } else {
6899 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
6900 init_server_map(curproxy);
6901 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006902 break;
6903 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006904
6905 if (curproxy->options & PR_O_LOGASAP)
6906 curproxy->to_log &= ~LW_BYTES;
6907
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006908 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01006909 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02006910 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
6911 proxy_type_str(curproxy), curproxy->id);
6912 err_code |= ERR_WARN;
6913 }
6914
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006915 if (curproxy->mode != PR_MODE_HTTP) {
6916 int optnum;
6917
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006918 if (curproxy->uri_auth) {
6919 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
6920 proxy_type_str(curproxy), curproxy->id);
6921 err_code |= ERR_WARN;
6922 curproxy->uri_auth = NULL;
6923 }
6924
Willy Tarreau87cf5142011-08-19 22:57:24 +02006925 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006926 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6927 "forwardfor", proxy_type_str(curproxy), curproxy->id);
6928 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02006929 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006930 }
6931
6932 if (curproxy->options & PR_O_ORGTO) {
6933 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6934 "originalto", proxy_type_str(curproxy), curproxy->id);
6935 err_code |= ERR_WARN;
6936 curproxy->options &= ~PR_O_ORGTO;
6937 }
6938
6939 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
6940 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
6941 (curproxy->cap & cfg_opts[optnum].cap) &&
6942 (curproxy->options & cfg_opts[optnum].val)) {
6943 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6944 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
6945 err_code |= ERR_WARN;
6946 curproxy->options &= ~cfg_opts[optnum].val;
6947 }
6948 }
6949
6950 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
6951 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
6952 (curproxy->cap & cfg_opts2[optnum].cap) &&
6953 (curproxy->options2 & cfg_opts2[optnum].val)) {
6954 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
6955 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
6956 err_code |= ERR_WARN;
6957 curproxy->options2 &= ~cfg_opts2[optnum].val;
6958 }
6959 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006960
Pieter Baauwd551fb52013-05-08 22:49:23 +02006961#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006962 if (curproxy->conn_src.bind_hdr_occ) {
6963 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006964 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01006965 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006966 err_code |= ERR_WARN;
6967 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02006968#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01006969 }
6970
Willy Tarreaubaaee002006-06-26 02:48:02 +02006971 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01006972 * ensure that we're not cross-dressing a TCP server into HTTP.
6973 */
6974 newsrv = curproxy->srv;
6975 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01006976 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006977 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
6978 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006979 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01006980 }
Willy Tarreaubce70882009-09-07 11:51:47 +02006981
Willy Tarreau0cec3312011-10-31 13:49:26 +01006982 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
6983 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
6984 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6985 err_code |= ERR_WARN;
6986 }
6987
Willy Tarreauc93cd162014-05-13 15:54:22 +02006988 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02006989 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
6990 proxy_type_str(curproxy), curproxy->id, newsrv->id);
6991 err_code |= ERR_WARN;
6992 }
6993
Pieter Baauwd551fb52013-05-08 22:49:23 +02006994#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01006995 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
6996 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02006997 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 +01006998 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006999 err_code |= ERR_WARN;
7000 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007001#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007002 newsrv = newsrv->next;
7003 }
7004
Willy Tarreau7fc7ebd2014-09-16 16:21:19 +02007005 /* check if we have a frontend with "tcp-request content" looking at L7
7006 * with no inspect-delay
7007 */
7008 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7009 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7010 if (trule->action == TCP_ACT_CAPTURE &&
7011 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7012 break;
7013 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7014 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7015 break;
7016 }
7017
7018 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7019 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7020 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7021 " This means that these rules will randomly find their contents. This can be fixed by"
7022 " setting the tcp-request inspect-delay.\n",
7023 proxy_type_str(curproxy), curproxy->id);
7024 err_code |= ERR_WARN;
7025 }
7026 }
7027
Willy Tarreauc1a21672009-08-16 22:37:44 +02007028 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007029 if (!curproxy->accept)
7030 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007031
Willy Tarreauc1a21672009-08-16 22:37:44 +02007032 if (curproxy->tcp_req.inspect_delay ||
7033 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007034 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007035
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007036 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007037 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007038 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007039 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007040
7041 /* both TCP and HTTP must check switching rules */
7042 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7043 }
7044
7045 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007046 if (curproxy->tcp_req.inspect_delay ||
7047 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7048 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7049
Emeric Brun97679e72010-09-23 17:56:44 +02007050 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7051 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7052
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007053 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007054 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007055 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007056 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007057
7058 /* If the backend does requires RDP cookie persistence, we have to
7059 * enable the corresponding analyser.
7060 */
7061 if (curproxy->options2 & PR_O2_RDPC_PRST)
7062 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7063 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007064 }
7065
7066 /***********************************************************/
7067 /* At this point, target names have already been resolved. */
7068 /***********************************************************/
7069
7070 /* Check multi-process mode compatibility */
7071
7072 if (global.nbproc > 1 && global.stats_fe) {
7073 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7074 unsigned long mask;
7075
7076 mask = nbits(global.nbproc);
7077 if (global.stats_fe->bind_proc)
7078 mask &= global.stats_fe->bind_proc;
7079
7080 if (bind_conf->bind_proc)
7081 mask &= bind_conf->bind_proc;
7082
7083 /* stop here if more than one process is used */
7084 if (popcount(mask) > 1)
7085 break;
7086 }
7087 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7088 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");
7089 }
7090 }
7091
7092 /* Make each frontend inherit bind-process from its listeners when not specified. */
7093 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7094 if (curproxy->bind_proc)
7095 continue;
7096
7097 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7098 unsigned long mask;
7099
7100 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7101 curproxy->bind_proc |= mask;
7102 }
7103
7104 if (!curproxy->bind_proc)
7105 curproxy->bind_proc = ~0UL;
7106 }
7107
7108 if (global.stats_fe) {
7109 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7110 unsigned long mask;
7111
7112 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7113 global.stats_fe->bind_proc |= mask;
7114 }
7115 if (!global.stats_fe->bind_proc)
7116 global.stats_fe->bind_proc = ~0UL;
7117 }
7118
Willy Tarreaub3228c82014-10-01 20:50:17 +02007119 /* propagate bindings from frontends to backends. Don't do it if there
7120 * are any fatal errors as we must not call it with unresolved proxies.
7121 */
7122 if (!cfgerr) {
7123 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7124 if (curproxy->cap & PR_CAP_FE)
7125 propagate_processes(curproxy, NULL);
7126 }
Willy Tarreau91b00c22014-09-16 13:41:21 +02007127 }
7128
7129 /* Bind each unbound backend to all processes when not specified. */
7130 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7131 if (curproxy->bind_proc)
7132 continue;
7133 curproxy->bind_proc = ~0UL;
7134 }
7135
7136 /*******************************************************/
7137 /* At this step, all proxies have a non-null bind_proc */
7138 /*******************************************************/
7139
7140 /* perform the final checks before creating tasks */
7141
7142 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7143 struct listener *listener;
7144 unsigned int next_id;
7145 int nbproc;
7146
7147 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007148
Emeric Brunc52962f2012-11-15 18:28:02 +01007149#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007150 /* Configure SSL for each bind line.
7151 * Note: if configuration fails at some point, the ->ctx member
7152 * remains NULL so that listeners can later detach.
7153 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007154 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007155 int alloc_ctx;
7156
Emeric Brunc52962f2012-11-15 18:28:02 +01007157 if (!bind_conf->is_ssl) {
7158 if (bind_conf->default_ctx) {
7159 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7160 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7161 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007162 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007163 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007164 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007165 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007166 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007167 cfgerr++;
7168 continue;
7169 }
7170
Emeric Brun8dc60392014-05-09 13:52:00 +02007171 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007172 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007173 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7174 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");
7175 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007176 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007177 cfgerr++;
7178 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007179 }
7180
Emeric Brunfc0421f2012-09-07 17:30:07 +02007181 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007182 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007183 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007184#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007185
Willy Tarreaue6b98942007-10-29 01:09:36 +01007186 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007187 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007188 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007189 if (!listener->luid) {
7190 /* listener ID not set, use automatic numbering with first
7191 * spare entry starting with next_luid.
7192 */
7193 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7194 listener->conf.id.key = listener->luid = next_id;
7195 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007196 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007197 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007198
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007199 /* enable separate counters */
7200 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7201 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007202 if (!listener->name)
7203 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007204 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007205
Willy Tarreaue6b98942007-10-29 01:09:36 +01007206 if (curproxy->options & PR_O_TCP_NOLING)
7207 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007208 if (!listener->maxconn)
7209 listener->maxconn = curproxy->maxconn;
7210 if (!listener->backlog)
7211 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007212 if (!listener->maxaccept)
7213 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7214
7215 /* we want to have an optimal behaviour on single process mode to
7216 * maximize the work at once, but in multi-process we want to keep
7217 * some fairness between processes, so we target half of the max
7218 * number of events to be balanced over all the processes the proxy
7219 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7220 * used to disable the limit.
7221 */
7222 if (listener->maxaccept > 0) {
7223 if (nbproc > 1)
7224 listener->maxaccept = (listener->maxaccept + 1) / 2;
7225 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7226 }
7227
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007228 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007229 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007230 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007231 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007232
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007233 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7234 listener->options |= LI_O_TCP_RULES;
7235
Willy Tarreaude3041d2010-05-31 10:56:17 +02007236 if (curproxy->mon_mask.s_addr)
7237 listener->options |= LI_O_CHK_MONNET;
7238
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007239 /* smart accept mode is automatic in HTTP mode */
7240 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007241 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007242 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7243 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007244 }
7245
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007246 /* Release unused SSL configs */
7247 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7248 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007249 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007250#ifdef USE_OPENSSL
7251 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007252 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007253 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007254 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007255 free(bind_conf->crl_file);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007256#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007257 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007258
Willy Tarreau102df612014-05-07 23:56:38 +02007259 if (nbproc > 1) {
7260 if (curproxy->uri_auth) {
Willy Tarreau036a83e2014-09-16 15:11:04 +02007261 int count, maxproc = 0;
7262
7263 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7264 count = popcount(bind_conf->bind_proc);
7265 if (count > maxproc)
7266 maxproc = count;
7267 }
7268 /* backends have 0, frontends have 1 or more */
7269 if (maxproc != 1)
7270 Warning("Proxy '%s': in multi-process mode, stats will be"
7271 " limited to process assigned to the current request.\n",
7272 curproxy->id);
7273
Willy Tarreau102df612014-05-07 23:56:38 +02007274 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7275 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7276 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007277 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007278 }
Willy Tarreau102df612014-05-07 23:56:38 +02007279 if (curproxy->appsession_name) {
7280 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7281 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007282 }
Willy Tarreau102df612014-05-07 23:56:38 +02007283 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7284 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7285 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007286 }
7287 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007288
7289 /* create the task associated with the proxy */
7290 curproxy->task = task_new();
7291 if (curproxy->task) {
7292 curproxy->task->context = curproxy;
7293 curproxy->task->process = manage_proxy;
7294 /* no need to queue, it will be done automatically if some
7295 * listener gets limited.
7296 */
7297 curproxy->task->expire = TICK_ETERNITY;
7298 } else {
7299 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7300 curproxy->id);
7301 cfgerr++;
7302 }
Willy Tarreaue56c4f12014-09-16 13:21:03 +02007303 }
7304
Willy Tarreaufbb78422011-06-05 15:38:35 +02007305 /* automatically compute fullconn if not set. We must not do it in the
7306 * loop above because cross-references are not yet fully resolved.
7307 */
7308 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7309 /* If <fullconn> is not set, let's set it to 10% of the sum of
7310 * the possible incoming frontend's maxconns.
7311 */
7312 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7313 struct proxy *fe;
7314 int total = 0;
7315
7316 /* sum up the number of maxconns of frontends which
7317 * reference this backend at least once or which are
7318 * the same one ('listen').
7319 */
7320 for (fe = proxy; fe; fe = fe->next) {
7321 struct switching_rule *rule;
7322 struct hdr_exp *exp;
7323 int found = 0;
7324
7325 if (!(fe->cap & PR_CAP_FE))
7326 continue;
7327
7328 if (fe == curproxy) /* we're on a "listen" instance */
7329 found = 1;
7330
7331 if (fe->defbe.be == curproxy) /* "default_backend" */
7332 found = 1;
7333
7334 /* check if a "use_backend" rule matches */
7335 if (!found) {
7336 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007337 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007338 found = 1;
7339 break;
7340 }
7341 }
7342 }
7343
7344 /* check if a "reqsetbe" rule matches */
7345 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7346 if (exp->action == ACT_SETBE &&
7347 (struct proxy *)exp->replace == curproxy) {
7348 found = 1;
7349 break;
7350 }
7351 }
7352
7353 /* now we've checked all possible ways to reference a backend
7354 * from a frontend.
7355 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007356 if (!found)
7357 continue;
7358 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007359 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007360 /* we have the sum of the maxconns in <total>. We only
7361 * keep 10% of that sum to set the default fullconn, with
7362 * a hard minimum of 1 (to avoid a divide by zero).
7363 */
7364 curproxy->fullconn = (total + 9) / 10;
7365 if (!curproxy->fullconn)
7366 curproxy->fullconn = 1;
7367 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007368 }
7369
Willy Tarreau056f5682010-06-06 15:51:11 +02007370 /* initialize stick-tables on backend capable proxies. This must not
7371 * be done earlier because the data size may be discovered while parsing
7372 * other proxies.
7373 */
Godbach9703e662013-12-11 21:11:41 +08007374 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007375 if (curproxy->state == PR_STSTOPPED)
7376 continue;
7377
Godbach9703e662013-12-11 21:11:41 +08007378 if (!stktable_init(&curproxy->table)) {
7379 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7380 cfgerr++;
7381 }
7382 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007383
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007384 /*
7385 * Recount currently required checks.
7386 */
7387
7388 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7389 int optnum;
7390
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007391 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7392 if (curproxy->options & cfg_opts[optnum].val)
7393 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007394
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007395 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7396 if (curproxy->options2 & cfg_opts2[optnum].val)
7397 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007398 }
7399
Willy Tarreau122541c2011-09-07 21:24:49 +02007400 if (peers) {
7401 struct peers *curpeers = peers, **last;
7402 struct peer *p, *pb;
7403
7404 /* Remove all peers sections which don't have a valid listener.
7405 * This can happen when a peers section is never referenced and
7406 * does not contain a local peer.
7407 */
7408 last = &peers;
7409 while (*last) {
7410 curpeers = *last;
7411 if (curpeers->peers_fe) {
7412 last = &curpeers->next;
7413 continue;
7414 }
7415
7416 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7417 curpeers->id, localpeer);
7418
7419 p = curpeers->remote;
7420 while (p) {
7421 pb = p->next;
7422 free(p->id);
7423 free(p);
7424 p = pb;
7425 }
7426
7427 /* Destroy and unlink this curpeers section.
7428 * Note: curpeers is backed up into *last.
7429 */
7430 free(curpeers->id);
7431 curpeers = curpeers->next;
7432 free(*last);
7433 *last = curpeers;
7434 }
7435 }
7436
Willy Tarreau34eb6712011-10-24 18:15:04 +02007437 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007438 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007439 MEM_F_SHARED);
7440
Willy Tarreaubb925012009-07-23 13:36:36 +02007441 if (cfgerr > 0)
7442 err_code |= ERR_ALERT | ERR_FATAL;
7443 out:
7444 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007445}
7446
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007447/*
7448 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7449 * parsing sessions.
7450 */
7451void cfg_register_keywords(struct cfg_kw_list *kwl)
7452{
7453 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7454}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007455
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007456/*
7457 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7458 */
7459void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7460{
7461 LIST_DEL(&kwl->list);
7462 LIST_INIT(&kwl->list);
7463}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007464
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007465/* this function register new section in the haproxy configuration file.
7466 * <section_name> is the name of this new section and <section_parser>
7467 * is the called parser. If two section declaration have the same name,
7468 * only the first declared is used.
7469 */
7470int cfg_register_section(char *section_name,
7471 int (*section_parser)(const char *, int, char **, int))
7472{
7473 struct cfg_section *cs;
7474
7475 cs = calloc(1, sizeof(*cs));
7476 if (!cs) {
7477 Alert("register section '%s': out of memory.\n", section_name);
7478 return 0;
7479 }
7480
7481 cs->section_name = section_name;
7482 cs->section_parser = section_parser;
7483
7484 LIST_ADDQ(&sections, &cs->list);
7485
7486 return 1;
7487}
7488
Willy Tarreaubaaee002006-06-26 02:48:02 +02007489/*
7490 * Local variables:
7491 * c-indent-level: 8
7492 * c-basic-offset: 8
7493 * End:
7494 */