blob: 2ebc9513737b5ee6c84bc93a436ab7f23ce7e0f8 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreaueb0c6142007-05-07 00:53:22 +020053#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010054#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020056#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020058#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020059#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020060#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020061#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020062#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010063#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020064#include <proto/lb_fwlc.h>
65#include <proto/lb_fwrr.h>
66#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020069#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020071#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010072#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010073#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020074#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020075#include <proto/sample.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020076#include <proto/server.h>
Willy Tarreau3bc13772008-12-07 11:50:35 +010077#include <proto/session.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020078#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020079#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010080#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081
Emeric Brunfc0421f2012-09-07 17:30:07 +020082#ifdef USE_OPENSSL
83#include <types/ssl_sock.h>
84#include <proto/ssl_sock.h>
85#include <proto/shctx.h>
86#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020087
Willy Tarreauf3c69202006-07-09 16:42:34 +020088/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
89 * ssl-hello-chk option to ensure that the remote server speaks SSL.
90 *
91 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
92 */
93const char sslv3_client_hello_pkt[] = {
94 "\x16" /* ContentType : 0x16 = Hanshake */
95 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
96 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
97 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
98 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
99 "\x03\x00" /* Hello Version : 0x0300 = v3 */
100 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
101 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
102 "\x00" /* Session ID length : empty (no session ID) */
103 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
104 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
105 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
106 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
107 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
108 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
109 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
110 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
111 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
112 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
113 "\x00\x38" "\x00\x39" "\x00\x3A"
114 "\x01" /* Compression Length : 0x01 = 1 byte for types */
115 "\x00" /* Compression Type : 0x00 = NULL compression */
116};
117
Willy Tarreau3842f002009-06-14 11:39:52 +0200118/* various keyword modifiers */
119enum kw_mod {
120 KWM_STD = 0, /* normal */
121 KWM_NO, /* "no" prefixed before the keyword */
122 KWM_DEF, /* "default" prefixed before the keyword */
123};
124
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100125/* permit to store configuration section */
126struct cfg_section {
127 struct list list;
128 char *section_name;
129 int (*section_parser)(const char *, int, char **, int);
130};
131
132/* Used to chain configuration sections definitions. This list
133 * stores struct cfg_section
134 */
135struct list sections = LIST_HEAD_INIT(sections);
136
Willy Tarreau13943ab2006-12-31 00:24:10 +0100137/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100138struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139 const char *name;
140 unsigned int val;
141 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100142 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100143 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100144};
145
146/* proxy->options */
147static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100148{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100149 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
150 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
151 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
152 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
153 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
154 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100155 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100156 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
158 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
159 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
160 { "redispatch", PR_O_REDISP, PR_CAP_BE, 0, 0 },
161 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100162#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100164#else
165 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100166#endif
167
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100169};
170
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100171/* proxy->options2 */
172static const struct cfg_opt cfg_opts2[] =
173{
174#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100175 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
176 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
177 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100178#else
179 { "splice-request", 0, 0, 0, 0 },
180 { "splice-response", 0, 0, 0, 0 },
181 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100182#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100183 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
184 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
185 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
186 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
187 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
188 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
189 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
190 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
191 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400192 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100193 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200194 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200195 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100196 { NULL, 0, 0, 0 }
197};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200198
Willy Tarreau6daf3432008-01-22 16:44:08 +0100199static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
201int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100202int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200204/* List head of all known configuration keywords */
205static struct cfg_kw_list cfg_keywords = {
206 .list = LIST_HEAD_INIT(cfg_keywords.list)
207};
208
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209/*
210 * converts <str> to a list of listeners which are dynamically allocated.
211 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
212 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
213 * - <port> is a numerical port from 1 to 65535 ;
214 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
215 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200216 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
217 * not NULL, it must be a valid pointer to either NULL or a freeable area that
218 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200219 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200220int 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 +0200221{
222 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100223 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 int port, end;
225
226 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200227
Willy Tarreaubaaee002006-06-26 02:48:02 +0200228 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100229 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100230 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231
232 str = next;
233 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100234 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200235 *next++ = 0;
236 }
237
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100238 ss2 = str2sa_range(str, &port, &end, err,
239 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
240 if (!ss2)
241 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200242
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100244 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200245 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100246 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200247 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100249 if (!port || !end) {
250 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
251 goto fail;
252 }
253
Emeric Bruned760922010-10-22 17:59:25 +0200254 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200255 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200256 goto fail;
257 }
258
259 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200260 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200261 goto fail;
262 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200263 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100264 else if (ss2->ss_family == AF_UNSPEC) {
265 socklen_t addr_len;
266
267 /* We want to attach to an already bound fd whose number
268 * is in the addr part of ss2 when cast to sockaddr_in.
269 * Note that by definition there is a single listener.
270 * We still have to determine the address family to
271 * register the correct protocol.
272 */
273 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
274 addr_len = sizeof(*ss2);
275 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
276 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
277 goto fail;
278 }
279
280 port = end = get_host_port(ss2);
281 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200282
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100283 /* OK the address looks correct */
284 ss = *ss2;
285
Willy Tarreaubaaee002006-06-26 02:48:02 +0200286 for (; port <= end; port++) {
287 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100288 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200289 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
290 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
291 l->frontend = curproxy;
292 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200293
Willy Tarreau40aa0702013-03-10 23:51:38 +0100294 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200296 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100297 l->state = LI_INIT;
298
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100299 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200300 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100301 tcpv4_add_listener(l);
302 }
Emeric Bruned760922010-10-22 17:59:25 +0200303 else if (ss.ss_family == AF_INET6) {
304 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
305 tcpv6_add_listener(l);
306 }
307 else {
Emeric Bruned760922010-10-22 17:59:25 +0200308 uxst_add_listener(l);
309 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200310
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200311 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100312 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200313 } /* end for(port) */
314 } /* end while(next) */
315 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200317 fail:
318 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200319 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320}
321
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200322/* Report a warning if a rule is placed after a 'tcp-request content' rule.
323 * Return 1 if the warning has been emitted, otherwise 0.
324 */
325int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
326{
327 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
328 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
329 file, line, arg);
330 return 1;
331 }
332 return 0;
333}
334
Willy Tarreau61d18892009-03-31 10:49:21 +0200335/* Report a warning if a rule is placed after a 'block' rule.
336 * Return 1 if the warning has been emitted, otherwise 0.
337 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100338int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200339{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200340 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200341 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
342 file, line, arg);
343 return 1;
344 }
345 return 0;
346}
347
Willy Tarreau5002f572014-04-23 01:32:02 +0200348/* Report a warning if a rule is placed after an 'http_request' rule.
349 * Return 1 if the warning has been emitted, otherwise 0.
350 */
351int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
352{
353 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
354 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
355 file, line, arg);
356 return 1;
357 }
358 return 0;
359}
360
Willy Tarreau61d18892009-03-31 10:49:21 +0200361/* Report a warning if a rule is placed after a reqrewrite rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100364int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200365{
366 if (proxy->req_exp) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
374/* Report a warning if a rule is placed after a reqadd rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100379 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
387/* Report a warning if a rule is placed after a redirect rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
392 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
393 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
400/* Report a warning if a rule is placed after a 'use_backend' rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
Willy Tarreauee445d92014-04-23 01:39:04 +0200413/* Report a warning if a rule is placed after a 'use-server' rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
416int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
417{
418 if (!LIST_ISEMPTY(&proxy->server_rules)) {
419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200426/* report a warning if a "tcp request connection" rule is dangerously placed */
427int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
428{
429 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
430 warnif_rule_after_block(proxy, file, line, arg) ||
431 warnif_rule_after_http_req(proxy, file, line, arg) ||
432 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
433 warnif_rule_after_reqadd(proxy, file, line, arg) ||
434 warnif_rule_after_redirect(proxy, file, line, arg) ||
435 warnif_rule_after_use_backend(proxy, file, line, arg) ||
436 warnif_rule_after_use_server(proxy, file, line, arg);
437}
438
439/* report a warning if a "tcp request content" rule is dangerously placed */
440int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
441{
442 return warnif_rule_after_block(proxy, file, line, arg) ||
443 warnif_rule_after_http_req(proxy, file, line, arg) ||
444 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
445 warnif_rule_after_reqadd(proxy, file, line, arg) ||
446 warnif_rule_after_redirect(proxy, file, line, arg) ||
447 warnif_rule_after_use_backend(proxy, file, line, arg) ||
448 warnif_rule_after_use_server(proxy, file, line, arg);
449}
450
Willy Tarreau61d18892009-03-31 10:49:21 +0200451/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100452int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200453{
Willy Tarreau5002f572014-04-23 01:32:02 +0200454 return warnif_rule_after_http_req(proxy, file, line, arg) ||
455 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
456 warnif_rule_after_reqadd(proxy, file, line, arg) ||
457 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200458 warnif_rule_after_use_backend(proxy, file, line, arg) ||
459 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200460}
461
462/* report a warning if an http-request rule is dangerously placed */
463int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
464{
Willy Tarreau61d18892009-03-31 10:49:21 +0200465 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
466 warnif_rule_after_reqadd(proxy, file, line, arg) ||
467 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200468 warnif_rule_after_use_backend(proxy, file, line, arg) ||
469 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200470}
471
472/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100473int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200474{
475 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
476 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200477 warnif_rule_after_use_backend(proxy, file, line, arg) ||
478 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200479}
480
481/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100482int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200483{
484 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200485 warnif_rule_after_use_backend(proxy, file, line, arg) ||
486 warnif_rule_after_use_server(proxy, file, line, arg);
487}
488
489/* report a warning if a redirect rule is dangerously placed */
490int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
491{
492 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
493 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200494}
495
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100496/* Report it if a request ACL condition uses some keywords that are incompatible
497 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
498 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
499 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100500 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100501static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100502{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100503 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200504 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100505
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100506 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100507 return 0;
508
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100509 acl = acl_cond_conflicts(cond, where);
510 if (acl) {
511 if (acl->name && *acl->name)
512 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
513 file, line, acl->name, sample_ckp_names(where));
514 else
515 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 +0200516 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100517 return ERR_WARN;
518 }
519 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100520 return 0;
521
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100522 if (acl->name && *acl->name)
523 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200524 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100525 else
526 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200527 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100528 return ERR_WARN;
529}
530
Willy Tarreaubaaee002006-06-26 02:48:02 +0200531/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200532 * parse a line in a <global> section. Returns the error code, 0 if OK, or
533 * any combination of :
534 * - ERR_ABORT: must abort ASAP
535 * - ERR_FATAL: we can continue parsing but not start the service
536 * - ERR_WARN: a warning has been emitted
537 * - ERR_ALERT: an alert has been emitted
538 * Only the two first ones can stop processing, the two others are just
539 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200540 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200541int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200542{
Willy Tarreau058e9072009-07-20 09:30:05 +0200543 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200544 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200545
546 if (!strcmp(args[0], "global")) { /* new section */
547 /* no option, nothing special to do */
Willy Tarreau058e9072009-07-20 09:30:05 +0200548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200549 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200550 else if (!strcmp(args[0], "ca-base")) {
551#ifdef USE_OPENSSL
552 if (global.ca_base != NULL) {
553 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
554 err_code |= ERR_ALERT;
555 goto out;
556 }
557 if (*(args[1]) == 0) {
558 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
559 err_code |= ERR_ALERT | ERR_FATAL;
560 goto out;
561 }
562 global.ca_base = strdup(args[1]);
563#else
564 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
565 err_code |= ERR_ALERT | ERR_FATAL;
566 goto out;
567#endif
568 }
569 else if (!strcmp(args[0], "crt-base")) {
570#ifdef USE_OPENSSL
571 if (global.crt_base != NULL) {
572 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
573 err_code |= ERR_ALERT;
574 goto out;
575 }
576 if (*(args[1]) == 0) {
577 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
578 err_code |= ERR_ALERT | ERR_FATAL;
579 goto out;
580 }
581 global.crt_base = strdup(args[1]);
582#else
583 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
584 err_code |= ERR_ALERT | ERR_FATAL;
585 goto out;
586#endif
587 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200588 else if (!strcmp(args[0], "daemon")) {
589 global.mode |= MODE_DAEMON;
590 }
591 else if (!strcmp(args[0], "debug")) {
592 global.mode |= MODE_DEBUG;
593 }
594 else if (!strcmp(args[0], "noepoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100595 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200597 else if (!strcmp(args[0], "nokqueue")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100598 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200599 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200600 else if (!strcmp(args[0], "nopoll")) {
Willy Tarreau43b78992009-01-25 15:42:27 +0100601 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200602 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100603 else if (!strcmp(args[0], "nosplice")) {
604 global.tune.options &= ~GTUNE_USE_SPLICE;
605 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200606 else if (!strcmp(args[0], "nogetaddrinfo")) {
607 global.tune.options &= ~GTUNE_USE_GAI;
608 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200609 else if (!strcmp(args[0], "quiet")) {
610 global.mode |= MODE_QUIET;
611 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200612 else if (!strcmp(args[0], "tune.maxpollevents")) {
613 if (global.tune.maxpollevents != 0) {
614 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200615 err_code |= ERR_ALERT;
616 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200617 }
618 if (*(args[1]) == 0) {
619 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200620 err_code |= ERR_ALERT | ERR_FATAL;
621 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200622 }
623 global.tune.maxpollevents = atol(args[1]);
624 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100625 else if (!strcmp(args[0], "tune.maxaccept")) {
626 if (global.tune.maxaccept != 0) {
627 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200628 err_code |= ERR_ALERT;
629 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100630 }
631 if (*(args[1]) == 0) {
632 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100635 }
636 global.tune.maxaccept = atol(args[1]);
637 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200638 else if (!strcmp(args[0], "tune.chksize")) {
639 if (*(args[1]) == 0) {
640 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
641 err_code |= ERR_ALERT | ERR_FATAL;
642 goto out;
643 }
644 global.tune.chksize = atol(args[1]);
645 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200646#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200647 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
648 global.tune.sslprivatecache = 1;
649 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100650 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
Emeric Brunfc32aca2012-09-03 12:10:29 +0200651 if (*(args[1]) == 0) {
652 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
653 err_code |= ERR_ALERT | ERR_FATAL;
654 goto out;
655 }
656 global.tune.sslcachesize = atol(args[1]);
657 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100658 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
659 unsigned int ssllifetime;
660 const char *res;
661
662 if (*(args[1]) == 0) {
663 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
664 err_code |= ERR_ALERT | ERR_FATAL;
665 goto out;
666 }
667
668 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
669 if (res) {
670 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
671 file, linenum, *res, args[0]);
672 err_code |= ERR_ALERT | ERR_FATAL;
673 goto out;
674 }
675
676 global.tune.ssllifetime = ssllifetime;
677 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100678 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
679 if (*(args[1]) == 0) {
680 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
681 err_code |= ERR_ALERT | ERR_FATAL;
682 goto out;
683 }
684 global.tune.ssl_max_record = atol(args[1]);
685 }
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200686 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
687 if (*(args[1]) == 0) {
688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
689 err_code |= ERR_ALERT | ERR_FATAL;
690 goto out;
691 }
692 global.tune.ssl_default_dh_param = atol(args[1]);
693 if (global.tune.ssl_default_dh_param < 1024) {
694 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
695 err_code |= ERR_ALERT | ERR_FATAL;
696 goto out;
697 }
698 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200699#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100700 else if (!strcmp(args[0], "tune.buffers.limit")) {
701 if (*(args[1]) == 0) {
702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
703 err_code |= ERR_ALERT | ERR_FATAL;
704 goto out;
705 }
706 global.tune.buf_limit = atol(args[1]);
707 if (global.tune.buf_limit) {
708 if (global.tune.buf_limit < 3)
709 global.tune.buf_limit = 3;
710 if (global.tune.buf_limit <= global.tune.reserved_bufs)
711 global.tune.buf_limit = global.tune.reserved_bufs + 1;
712 }
713 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100714 else if (!strcmp(args[0], "tune.buffers.reserve")) {
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.reserved_bufs = atol(args[1]);
721 if (global.tune.reserved_bufs < 2)
722 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100723 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
724 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100725 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200726 else if (!strcmp(args[0], "tune.bufsize")) {
727 if (*(args[1]) == 0) {
728 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
729 err_code |= ERR_ALERT | ERR_FATAL;
730 goto out;
731 }
732 global.tune.bufsize = atol(args[1]);
733 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
734 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100735 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100736 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200737 }
738 else if (!strcmp(args[0], "tune.maxrewrite")) {
739 if (*(args[1]) == 0) {
740 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744 global.tune.maxrewrite = atol(args[1]);
745 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
746 global.tune.maxrewrite = global.tune.bufsize / 2;
747 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100748 else if (!strcmp(args[0], "tune.idletimer")) {
749 unsigned int idle;
750 const char *res;
751
752 if (*(args[1]) == 0) {
753 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757
758 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
759 if (res) {
760 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
761 file, linenum, *res, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765
766 if (idle > 65535) {
767 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 global.tune.idle_timer = idle;
772 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100773 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
774 if (global.tune.client_rcvbuf != 0) {
775 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
776 err_code |= ERR_ALERT;
777 goto out;
778 }
779 if (*(args[1]) == 0) {
780 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
781 err_code |= ERR_ALERT | ERR_FATAL;
782 goto out;
783 }
784 global.tune.client_rcvbuf = atol(args[1]);
785 }
786 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
787 if (global.tune.server_rcvbuf != 0) {
788 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
789 err_code |= ERR_ALERT;
790 goto out;
791 }
792 if (*(args[1]) == 0) {
793 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
794 err_code |= ERR_ALERT | ERR_FATAL;
795 goto out;
796 }
797 global.tune.server_rcvbuf = atol(args[1]);
798 }
799 else if (!strcmp(args[0], "tune.sndbuf.client")) {
800 if (global.tune.client_sndbuf != 0) {
801 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
802 err_code |= ERR_ALERT;
803 goto out;
804 }
805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.client_sndbuf = atol(args[1]);
811 }
812 else if (!strcmp(args[0], "tune.sndbuf.server")) {
813 if (global.tune.server_sndbuf != 0) {
814 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
815 err_code |= ERR_ALERT;
816 goto out;
817 }
818 if (*(args[1]) == 0) {
819 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
820 err_code |= ERR_ALERT | ERR_FATAL;
821 goto out;
822 }
823 global.tune.server_sndbuf = atol(args[1]);
824 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200825 else if (!strcmp(args[0], "tune.pipesize")) {
826 if (*(args[1]) == 0) {
827 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
828 err_code |= ERR_ALERT | ERR_FATAL;
829 goto out;
830 }
831 global.tune.pipesize = atol(args[1]);
832 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100833 else if (!strcmp(args[0], "tune.http.cookielen")) {
834 if (*(args[1]) == 0) {
835 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
836 err_code |= ERR_ALERT | ERR_FATAL;
837 goto out;
838 }
839 global.tune.cookie_len = atol(args[1]) + 1;
840 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200841 else if (!strcmp(args[0], "tune.http.maxhdr")) {
842 if (*(args[1]) == 0) {
843 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
844 err_code |= ERR_ALERT | ERR_FATAL;
845 goto out;
846 }
847 global.tune.max_http_hdr = atol(args[1]);
848 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100849 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
850#ifdef USE_ZLIB
851 if (*args[1]) {
852 global.tune.zlibmemlevel = atoi(args[1]);
853 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
854 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
855 file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 } else {
860 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
861 file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865#else
866 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
867 err_code |= ERR_ALERT | ERR_FATAL;
868 goto out;
869#endif
870 }
871 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
872#ifdef USE_ZLIB
873 if (*args[1]) {
874 global.tune.zlibwindowsize = atoi(args[1]);
875 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
876 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
877 file, linenum, args[0]);
878 err_code |= ERR_ALERT | ERR_FATAL;
879 goto out;
880 }
881 } else {
882 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
883 file, linenum, args[0]);
884 err_code |= ERR_ALERT | ERR_FATAL;
885 goto out;
886 }
887#else
888 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
889 err_code |= ERR_ALERT | ERR_FATAL;
890 goto out;
891#endif
892 }
William Lallemandf3747832012-11-09 12:33:10 +0100893 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
894 if (*args[1]) {
895 global.tune.comp_maxlevel = atoi(args[1]);
896 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
897 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
898 file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 } else {
903 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
904 file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200909 else if (!strcmp(args[0], "uid")) {
910 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200911 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200912 err_code |= ERR_ALERT;
913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200914 }
915 if (*(args[1]) == 0) {
916 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200917 err_code |= ERR_ALERT | ERR_FATAL;
918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200919 }
920 global.uid = atol(args[1]);
921 }
922 else if (!strcmp(args[0], "gid")) {
923 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200924 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200925 err_code |= ERR_ALERT;
926 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200927 }
928 if (*(args[1]) == 0) {
929 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200930 err_code |= ERR_ALERT | ERR_FATAL;
931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200932 }
933 global.gid = atol(args[1]);
934 }
Simon Horman98637e52014-06-20 12:30:16 +0900935 else if (!strcmp(args[0], "external-check")) {
936 global.external_check = 1;
937 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200938 /* user/group name handling */
939 else if (!strcmp(args[0], "user")) {
940 struct passwd *ha_user;
941 if (global.uid != 0) {
942 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200943 err_code |= ERR_ALERT;
944 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200945 }
946 errno = 0;
947 ha_user = getpwnam(args[1]);
948 if (ha_user != NULL) {
949 global.uid = (int)ha_user->pw_uid;
950 }
951 else {
952 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 +0200953 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200954 }
955 }
956 else if (!strcmp(args[0], "group")) {
957 struct group *ha_group;
958 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +0200959 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +0200960 err_code |= ERR_ALERT;
961 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200962 }
963 errno = 0;
964 ha_group = getgrnam(args[1]);
965 if (ha_group != NULL) {
966 global.gid = (int)ha_group->gr_gid;
967 }
968 else {
969 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 +0200970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +0200971 }
972 }
973 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +0200974 else if (!strcmp(args[0], "nbproc")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200975 if (*(args[1]) == 0) {
976 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200977 err_code |= ERR_ALERT | ERR_FATAL;
978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200979 }
980 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +0100981 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
982 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
983 file, linenum, args[0], LONGBITS, global.nbproc);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200987 }
988 else if (!strcmp(args[0], "maxconn")) {
989 if (global.maxconn != 0) {
990 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200991 err_code |= ERR_ALERT;
992 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200993 }
994 if (*(args[1]) == 0) {
995 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200998 }
999 global.maxconn = atol(args[1]);
1000#ifdef SYSTEM_MAXCONN
1001 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1002 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);
1003 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001004 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001005 }
1006#endif /* SYSTEM_MAXCONN */
1007 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001008 else if (!strcmp(args[0], "maxsslconn")) {
1009#ifdef USE_OPENSSL
1010 if (*(args[1]) == 0) {
1011 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1012 err_code |= ERR_ALERT | ERR_FATAL;
1013 goto out;
1014 }
1015 global.maxsslconn = atol(args[1]);
1016#else
Emeric Brun0914df82012-10-02 18:45:42 +02001017 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1018 err_code |= ERR_ALERT | ERR_FATAL;
1019 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001020#endif
1021 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001022 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1023#ifdef USE_OPENSSL
1024 if (*(args[1]) == 0) {
1025 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029 free(global.listen_default_ciphers);
1030 global.listen_default_ciphers = strdup(args[1]);
1031#else
1032 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1033 err_code |= ERR_ALERT | ERR_FATAL;
1034 goto out;
1035#endif
1036 }
1037 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1038#ifdef USE_OPENSSL
1039 if (*(args[1]) == 0) {
1040 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044 free(global.connect_default_ciphers);
1045 global.connect_default_ciphers = strdup(args[1]);
1046#else
1047 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1048 err_code |= ERR_ALERT | ERR_FATAL;
1049 goto out;
1050#endif
1051 }
Emeric Brun850efd52014-01-29 12:24:34 +01001052 else if (!strcmp(args[0], "ssl-server-verify")) {
1053 if (*(args[1]) == 0) {
1054 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 if (strcmp(args[1],"none") == 0)
1059 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1060 else if (strcmp(args[1],"required") == 0)
1061 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1062 else {
1063 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1064 err_code |= ERR_ALERT | ERR_FATAL;
1065 goto out;
1066 }
1067 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001068 else if (!strcmp(args[0], "maxconnrate")) {
1069 if (global.cps_lim != 0) {
1070 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1071 err_code |= ERR_ALERT;
1072 goto out;
1073 }
1074 if (*(args[1]) == 0) {
1075 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079 global.cps_lim = atol(args[1]);
1080 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001081 else if (!strcmp(args[0], "maxsessrate")) {
1082 if (global.sps_lim != 0) {
1083 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1084 err_code |= ERR_ALERT;
1085 goto out;
1086 }
1087 if (*(args[1]) == 0) {
1088 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1089 err_code |= ERR_ALERT | ERR_FATAL;
1090 goto out;
1091 }
1092 global.sps_lim = atol(args[1]);
1093 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001094 else if (!strcmp(args[0], "maxsslrate")) {
1095 if (global.ssl_lim != 0) {
1096 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1097 err_code |= ERR_ALERT;
1098 goto out;
1099 }
1100 if (*(args[1]) == 0) {
1101 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1102 err_code |= ERR_ALERT | ERR_FATAL;
1103 goto out;
1104 }
1105 global.ssl_lim = atol(args[1]);
1106 }
William Lallemandd85f9172012-11-09 17:05:39 +01001107 else if (!strcmp(args[0], "maxcomprate")) {
1108 if (*(args[1]) == 0) {
1109 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1110 err_code |= ERR_ALERT | ERR_FATAL;
1111 goto out;
1112 }
1113 global.comp_rate_lim = atoi(args[1]) * 1024;
1114 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001115 else if (!strcmp(args[0], "maxpipes")) {
1116 if (global.maxpipes != 0) {
1117 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001118 err_code |= ERR_ALERT;
1119 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001120 }
1121 if (*(args[1]) == 0) {
1122 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001123 err_code |= ERR_ALERT | ERR_FATAL;
1124 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001125 }
1126 global.maxpipes = atol(args[1]);
1127 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001128 else if (!strcmp(args[0], "maxzlibmem")) {
1129 if (*(args[1]) == 0) {
1130 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1131 err_code |= ERR_ALERT | ERR_FATAL;
1132 goto out;
1133 }
William Lallemande3a7d992012-11-20 11:25:20 +01001134 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001135 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001136 else if (!strcmp(args[0], "maxcompcpuusage")) {
1137 if (*(args[1]) == 0) {
1138 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1139 err_code |= ERR_ALERT | ERR_FATAL;
1140 goto out;
1141 }
1142 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001143 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001144 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
1147 }
1148}
1149
Willy Tarreaubaaee002006-06-26 02:48:02 +02001150 else if (!strcmp(args[0], "ulimit-n")) {
1151 if (global.rlimit_nofile != 0) {
1152 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001153 err_code |= ERR_ALERT;
1154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 }
1156 if (*(args[1]) == 0) {
1157 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001158 err_code |= ERR_ALERT | ERR_FATAL;
1159 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001160 }
1161 global.rlimit_nofile = atol(args[1]);
1162 }
1163 else if (!strcmp(args[0], "chroot")) {
1164 if (global.chroot != NULL) {
1165 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT;
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 if (*(args[1]) == 0) {
1170 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001173 }
1174 global.chroot = strdup(args[1]);
1175 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001176 else if (!strcmp(args[0], "description")) {
1177 int i, len=0;
1178 char *d;
1179
1180 if (!*args[1]) {
1181 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1182 file, linenum, args[0]);
1183 err_code |= ERR_ALERT | ERR_FATAL;
1184 goto out;
1185 }
1186
Willy Tarreau348acfe2014-04-14 15:00:39 +02001187 for (i = 1; *args[i]; i++)
1188 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001189
1190 if (global.desc)
1191 free(global.desc);
1192
1193 global.desc = d = (char *)calloc(1, len);
1194
Willy Tarreau348acfe2014-04-14 15:00:39 +02001195 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1196 for (i = 2; *args[i]; i++)
1197 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001198 }
1199 else if (!strcmp(args[0], "node")) {
1200 int i;
1201 char c;
1202
1203 for (i=0; args[1][i]; i++) {
1204 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001205 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1206 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001207 break;
1208 }
1209
1210 if (!i || args[1][i]) {
1211 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1212 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1213 file, linenum, args[0]);
1214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
1216 }
1217
1218 if (global.node)
1219 free(global.node);
1220
1221 global.node = strdup(args[1]);
1222 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001223 else if (!strcmp(args[0], "pidfile")) {
1224 if (global.pidfile != NULL) {
1225 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001226 err_code |= ERR_ALERT;
1227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001228 }
1229 if (*(args[1]) == 0) {
1230 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001231 err_code |= ERR_ALERT | ERR_FATAL;
1232 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001233 }
1234 global.pidfile = strdup(args[1]);
1235 }
Emeric Bruned760922010-10-22 17:59:25 +02001236 else if (!strcmp(args[0], "unix-bind")) {
1237 int cur_arg = 1;
1238 while (*(args[cur_arg])) {
1239 if (!strcmp(args[cur_arg], "prefix")) {
1240 if (global.unix_bind.prefix != NULL) {
1241 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1242 err_code |= ERR_ALERT;
1243 cur_arg += 2;
1244 continue;
1245 }
1246
1247 if (*(args[cur_arg+1]) == 0) {
1248 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1253 cur_arg += 2;
1254 continue;
1255 }
1256
1257 if (!strcmp(args[cur_arg], "mode")) {
1258
1259 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1260 cur_arg += 2;
1261 continue;
1262 }
1263
1264 if (!strcmp(args[cur_arg], "uid")) {
1265
1266 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1267 cur_arg += 2;
1268 continue;
1269 }
1270
1271 if (!strcmp(args[cur_arg], "gid")) {
1272
1273 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1274 cur_arg += 2;
1275 continue;
1276 }
1277
1278 if (!strcmp(args[cur_arg], "user")) {
1279 struct passwd *user;
1280
1281 user = getpwnam(args[cur_arg + 1]);
1282 if (!user) {
1283 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1284 file, linenum, args[0], args[cur_arg + 1 ]);
1285 err_code |= ERR_ALERT | ERR_FATAL;
1286 goto out;
1287 }
1288
1289 global.unix_bind.ux.uid = user->pw_uid;
1290 cur_arg += 2;
1291 continue;
1292 }
1293
1294 if (!strcmp(args[cur_arg], "group")) {
1295 struct group *group;
1296
1297 group = getgrnam(args[cur_arg + 1]);
1298 if (!group) {
1299 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1300 file, linenum, args[0], args[cur_arg + 1 ]);
1301 err_code |= ERR_ALERT | ERR_FATAL;
1302 goto out;
1303 }
1304
1305 global.unix_bind.ux.gid = group->gr_gid;
1306 cur_arg += 2;
1307 continue;
1308 }
1309
Willy Tarreaub48f9582011-09-05 01:17:06 +02001310 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001311 file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 }
William Lallemand0f99e342011-10-12 17:50:54 +02001316 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1317 /* delete previous herited or defined syslog servers */
1318 struct logsrv *back;
1319 struct logsrv *tmp;
1320
1321 if (*(args[1]) != 0) {
1322 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1323 err_code |= ERR_ALERT | ERR_FATAL;
1324 goto out;
1325 }
1326
1327 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1328 LIST_DEL(&tmp->list);
1329 free(tmp);
1330 }
1331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001332 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001333 struct sockaddr_storage *sk;
1334 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001335 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001336 int arg = 0;
1337 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001338
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 if (*(args[1]) == 0 || *(args[2]) == 0) {
1340 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001341 err_code |= ERR_ALERT | ERR_FATAL;
1342 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001343 }
William Lallemand0f99e342011-10-12 17:50:54 +02001344
1345 logsrv = calloc(1, sizeof(struct logsrv));
1346
Willy Tarreau18324f52014-06-27 18:10:07 +02001347 /* just after the address, a length may be specified */
1348 if (strcmp(args[arg+2], "len") == 0) {
1349 len = atoi(args[arg+3]);
1350 if (len < 80 || len > 65535) {
1351 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1352 file, linenum, args[arg+3]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
1356 logsrv->maxlen = len;
1357
1358 /* skip these two args */
1359 arg += 2;
1360 }
1361 else
1362 logsrv->maxlen = MAX_SYSLOG_LEN;
1363
1364 if (logsrv->maxlen > global.max_syslog_len) {
1365 global.max_syslog_len = logsrv->maxlen;
1366 logline = realloc(logline, global.max_syslog_len + 1);
1367 }
1368
1369 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001370 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001371 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001372 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001373 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 }
1375
William Lallemand0f99e342011-10-12 17:50:54 +02001376 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001377 if (*(args[arg+3])) {
1378 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001379 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001380 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001381 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001382 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001383 }
1384 }
1385
William Lallemand0f99e342011-10-12 17:50:54 +02001386 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001387 if (*(args[arg+4])) {
1388 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001389 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001390 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001391 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001392 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001393 }
1394 }
1395
Willy Tarreau902636f2013-03-10 19:44:48 +01001396 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001397 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001398 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001399 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001400 free(logsrv);
1401 goto out;
1402 }
1403 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001404
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001405 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001406 if (port1 != port2) {
1407 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1408 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001409 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001410 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001411 goto out;
1412 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001413
William Lallemand0f99e342011-10-12 17:50:54 +02001414 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001415 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001416 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418
William Lallemand0f99e342011-10-12 17:50:54 +02001419 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001420 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001421 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1422 char *name;
1423 int len;
1424
1425 if (global.log_send_hostname != NULL) {
1426 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1427 err_code |= ERR_ALERT;
1428 goto out;
1429 }
1430
1431 if (*(args[1]))
1432 name = args[1];
1433 else
1434 name = hostname;
1435
1436 len = strlen(name);
1437
1438 /* We'll add a space after the name to respect the log format */
1439 free(global.log_send_hostname);
1440 global.log_send_hostname = malloc(len + 2);
1441 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1442 }
Kevinm48936af2010-12-22 16:08:21 +00001443 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
1444 if (*(args[1]) == 0) {
1445 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449 free(global.log_tag);
1450 global.log_tag = strdup(args[1]);
1451 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001452 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
1453 if (global.spread_checks != 0) {
1454 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001455 err_code |= ERR_ALERT;
1456 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001457 }
1458 if (*(args[1]) == 0) {
1459 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001460 err_code |= ERR_ALERT | ERR_FATAL;
1461 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001462 }
1463 global.spread_checks = atol(args[1]);
1464 if (global.spread_checks < 0 || global.spread_checks > 50) {
1465 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001466 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001467 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001468 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001469 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1470 const char *err;
1471 unsigned int val;
1472
1473
1474 if (*(args[1]) == 0) {
1475 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1476 err_code |= ERR_ALERT | ERR_FATAL;
1477 goto out;
1478 }
1479
1480 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1481 if (err) {
1482 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1483 err_code |= ERR_ALERT | ERR_FATAL;
1484 }
1485 global.max_spread_checks = val;
1486 if (global.max_spread_checks < 0) {
1487 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1488 err_code |= ERR_ALERT | ERR_FATAL;
1489 }
1490 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001491 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1492#ifdef USE_CPU_AFFINITY
1493 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001494 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001495 unsigned long cpus = 0;
1496
1497 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001498 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001499 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001500 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001501 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001502 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001503 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001504 proc = atol(args[1]);
1505 if (proc >= 1 && proc <= LONGBITS)
1506 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001507 }
1508
1509 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001510 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",
1511 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001512 err_code |= ERR_ALERT | ERR_FATAL;
1513 goto out;
1514 }
1515
1516 cur_arg = 2;
1517 while (*args[cur_arg]) {
1518 unsigned int low, high;
1519
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001520 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001521 char *dash = strchr(args[cur_arg], '-');
1522
1523 low = high = str2uic(args[cur_arg]);
1524 if (dash)
1525 high = str2uic(dash + 1);
1526
1527 if (high < low) {
1528 unsigned int swap = low;
1529 low = high;
1530 high = swap;
1531 }
1532
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001533 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001534 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001535 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001536 err_code |= ERR_ALERT | ERR_FATAL;
1537 goto out;
1538 }
1539
1540 while (low <= high)
1541 cpus |= 1UL << low++;
1542 }
1543 else {
1544 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1545 file, linenum, args[0], args[cur_arg]);
1546 err_code |= ERR_ALERT | ERR_FATAL;
1547 goto out;
1548 }
1549 cur_arg++;
1550 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001551 for (i = 0; i < LONGBITS; i++)
1552 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001553 global.cpu_map[i] = cpus;
1554#else
1555 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1556 err_code |= ERR_ALERT | ERR_FATAL;
1557 goto out;
1558#endif
1559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001560 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001561 struct cfg_kw_list *kwl;
1562 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001563 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001564
1565 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1566 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1567 if (kwl->kw[index].section != CFG_GLOBAL)
1568 continue;
1569 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001570 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001571 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001572 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001573 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001574 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001575 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001576 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001577 err_code |= ERR_WARN;
1578 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001579 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001580 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001581 }
1582 }
1583 }
1584
Willy Tarreaubaaee002006-06-26 02:48:02 +02001585 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001586 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001588
Willy Tarreau058e9072009-07-20 09:30:05 +02001589 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001590 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001591 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001592}
1593
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001594void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001595{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001596 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001597 defproxy.mode = PR_MODE_TCP;
1598 defproxy.state = PR_STNEW;
1599 defproxy.maxconn = cfg_maxpconn;
1600 defproxy.conn_retries = CONN_RETRIES;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001601
Simon Horman66183002013-02-23 10:16:43 +09001602 defproxy.defsrv.check.inter = DEF_CHKINTR;
1603 defproxy.defsrv.check.fastinter = 0;
1604 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001605 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1606 defproxy.defsrv.agent.fastinter = 0;
1607 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001608 defproxy.defsrv.check.rise = DEF_RISETIME;
1609 defproxy.defsrv.check.fall = DEF_FALLTIME;
1610 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1611 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001612 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001613 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001614 defproxy.defsrv.maxqueue = 0;
1615 defproxy.defsrv.minconn = 0;
1616 defproxy.defsrv.maxconn = 0;
1617 defproxy.defsrv.slowstart = 0;
1618 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1619 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1620 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001621
1622 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001623}
1624
Willy Tarreauade5ec42010-01-28 19:33:49 +01001625
Willy Tarreau63af98d2014-05-18 08:11:41 +02001626/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1627 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1628 * ERR_FATAL in case of error.
1629 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001630static int create_cond_regex_rule(const char *file, int line,
1631 struct proxy *px, int dir, int action, int flags,
1632 const char *cmd, const char *reg, const char *repl,
1633 const char **cond_start)
1634{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001635 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001636 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001637 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001638 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001639 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001640 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001641 int cs;
1642 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001643
1644 if (px == &defproxy) {
1645 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001646 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001647 goto err;
1648 }
1649
1650 if (*reg == 0) {
1651 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\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
1656 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001657 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001658
Willy Tarreau5321c422010-01-28 20:35:13 +01001659 if (cond_start &&
1660 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001661 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1662 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1663 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001664 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001665 goto err;
1666 }
1667 }
1668 else if (cond_start && **cond_start) {
1669 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1670 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001671 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001672 goto err;
1673 }
1674
Willy Tarreau63af98d2014-05-18 08:11:41 +02001675 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001676 (dir == SMP_OPT_DIR_REQ) ?
1677 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1678 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1679 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001680
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001681 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001682 if (!preg) {
1683 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001684 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001685 goto err;
1686 }
1687
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001688 cs = !(flags & REG_ICASE);
1689 cap = !(flags & REG_NOSUB);
1690 error = NULL;
1691 if (!regex_comp(reg, preg, cs, cap, &error)) {
1692 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1693 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001694 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001695 goto err;
1696 }
1697
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001698 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001699 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001700 if (repl && err) {
1701 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1702 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001703 ret_code |= ERR_ALERT | ERR_FATAL;
1704 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001705 }
1706
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001707 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001708 ret_code |= ERR_WARN;
1709
1710 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001711
Willy Tarreau63af98d2014-05-18 08:11:41 +02001712 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001713 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001714 err:
1715 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001716 free(errmsg);
1717 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001718}
1719
Willy Tarreaubaaee002006-06-26 02:48:02 +02001720/*
Willy Tarreau977b8e42006-12-29 14:19:17 +01001721 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001722 * Returns the error code, 0 if OK, or any combination of :
1723 * - ERR_ABORT: must abort ASAP
1724 * - ERR_FATAL: we can continue parsing but not start the service
1725 * - ERR_WARN: a warning has been emitted
1726 * - ERR_ALERT: an alert has been emitted
1727 * Only the two first ones can stop processing, the two others are just
1728 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001729 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001730int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1731{
1732 static struct peers *curpeers = NULL;
1733 struct peer *newpeer = NULL;
1734 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001735 struct bind_conf *bind_conf;
1736 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001737 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001738 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001739
1740 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001741 if (!*args[1]) {
1742 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001743 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001744 goto out;
1745 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001746
1747 err = invalid_char(args[1]);
1748 if (err) {
1749 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1750 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001751 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001752 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001753 }
1754
1755 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1756 /*
1757 * If there are two proxies with the same name only following
1758 * combinations are allowed:
1759 */
1760 if (strcmp(curpeers->id, args[1]) == 0) {
1761 Warning("Parsing [%s:%d]: peers '%s' has same name as another peers (declared at %s:%d).\n",
1762 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
1763 err_code |= ERR_WARN;
1764 }
1765 }
1766
1767 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1768 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1769 err_code |= ERR_ALERT | ERR_ABORT;
1770 goto out;
1771 }
1772
1773 curpeers->next = peers;
1774 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001775 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001776 curpeers->conf.line = linenum;
1777 curpeers->last_change = now.tv_sec;
1778 curpeers->id = strdup(args[1]);
1779 }
1780 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001781 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001782 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001783 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001784
1785 if (!*args[2]) {
1786 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1787 file, linenum, args[0]);
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791
1792 err = invalid_char(args[1]);
1793 if (err) {
1794 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1795 file, linenum, *err, args[1]);
1796 err_code |= ERR_ALERT | ERR_FATAL;
1797 goto out;
1798 }
1799
1800 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
1801 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1802 err_code |= ERR_ALERT | ERR_ABORT;
1803 goto out;
1804 }
1805
1806 /* the peers are linked backwards first */
1807 curpeers->count++;
1808 newpeer->next = curpeers->remote;
1809 curpeers->remote = newpeer;
1810 newpeer->peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001811 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001812 newpeer->conf.line = linenum;
1813
1814 newpeer->last_change = now.tv_sec;
1815 newpeer->id = strdup(args[1]);
1816
Willy Tarreau902636f2013-03-10 19:44:48 +01001817 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001818 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001819 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01001820 err_code |= ERR_ALERT | ERR_FATAL;
1821 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001822 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01001823
1824 proto = protocol_by_family(sk->ss_family);
1825 if (!proto || !proto->connect) {
1826 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
1827 file, linenum, args[0], args[1]);
1828 err_code |= ERR_ALERT | ERR_FATAL;
1829 goto out;
1830 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001831
1832 if (port1 != port2) {
1833 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
1834 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
1837 }
1838
Willy Tarreau2aa38802013-02-20 19:20:59 +01001839 if (!port1) {
1840 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
1841 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01001845
Emeric Brun32da3c42010-09-23 18:39:19 +02001846 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001847 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02001848 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02001849 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02001850
Emeric Brun32da3c42010-09-23 18:39:19 +02001851 if (strcmp(newpeer->id, localpeer) == 0) {
1852 /* Current is local peer, it define a frontend */
1853 newpeer->local = 1;
1854
1855 if (!curpeers->peers_fe) {
1856 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
1857 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1858 err_code |= ERR_ALERT | ERR_ABORT;
1859 goto out;
1860 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001861
Willy Tarreau237250c2011-07-29 01:49:03 +02001862 init_new_proxy(curpeers->peers_fe);
1863 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02001864
1865 curpeers->peers_fe->last_change = now.tv_sec;
1866 curpeers->peers_fe->id = strdup(args[1]);
1867 curpeers->peers_fe->cap = PR_CAP_FE;
Willy Tarreau3ae65a12011-09-07 17:40:39 +02001868 curpeers->peers_fe->maxconn = 0;
Emeric Brun32da3c42010-09-23 18:39:19 +02001869 curpeers->peers_fe->conn_retries = CONN_RETRIES;
1870 curpeers->peers_fe->timeout.connect = 5000;
1871 curpeers->peers_fe->accept = peer_accept;
1872 curpeers->peers_fe->options2 |= PR_O2_INDEPSTR | PR_O2_SMARTCON | PR_O2_SMARTACC;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001873 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1874 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001875
1876 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1877
Willy Tarreau902636f2013-03-10 19:44:48 +01001878 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1879 if (errmsg && *errmsg) {
1880 indent_msg(&errmsg, 2);
1881 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001882 }
1883 else
1884 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1885 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001886 err_code |= ERR_FATAL;
1887 goto out;
1888 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001889
1890 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001891 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001892 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1893 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
1894 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1895 l->accept = session_accept;
1896 l->handler = process_session;
1897 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1898 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1899 global.maxsock += l->maxconn;
1900 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001901 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001902 else {
1903 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1904 file, linenum, args[0], args[1],
1905 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1906 err_code |= ERR_FATAL;
1907 goto out;
1908 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001909 }
1910 } /* neither "peer" nor "peers" */
1911 else if (*args[0] != 0) {
1912 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1913 err_code |= ERR_ALERT | ERR_FATAL;
1914 goto out;
1915 }
1916
1917out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001918 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001919 return err_code;
1920}
1921
Simon Horman0d16a402015-01-30 11:22:58 +09001922
1923/*
1924 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1925 * Returns the error code, 0 if OK, or any combination of :
1926 * - ERR_ABORT: must abort ASAP
1927 * - ERR_FATAL: we can continue parsing but not start the service
1928 * - ERR_WARN: a warning has been emitted
1929 * - ERR_ALERT: an alert has been emitted
1930 * Only the two first ones can stop processing, the two others are just
1931 * indicators.
1932 */
1933int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1934{
1935 static struct mailers *curmailers = NULL;
1936 struct mailer *newmailer = NULL;
1937 const char *err;
1938 int err_code = 0;
1939 char *errmsg = NULL;
1940
1941 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1942 if (!*args[1]) {
1943 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1944 err_code |= ERR_ALERT | ERR_ABORT;
1945 goto out;
1946 }
1947
1948 err = invalid_char(args[1]);
1949 if (err) {
1950 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1951 file, linenum, *err, args[0], args[1]);
1952 err_code |= ERR_ALERT | ERR_ABORT;
1953 goto out;
1954 }
1955
1956 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1957 /*
1958 * If there are two proxies with the same name only following
1959 * combinations are allowed:
1960 */
1961 if (strcmp(curmailers->id, args[1]) == 0) {
1962 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1963 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1964 err_code |= ERR_WARN;
1965 }
1966 }
1967
1968 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1969 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1970 err_code |= ERR_ALERT | ERR_ABORT;
1971 goto out;
1972 }
1973
1974 curmailers->next = mailers;
1975 mailers = curmailers;
1976 curmailers->conf.file = strdup(file);
1977 curmailers->conf.line = linenum;
1978 curmailers->id = strdup(args[1]);
1979 }
1980 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1981 struct sockaddr_storage *sk;
1982 int port1, port2;
1983 struct protocol *proto;
1984
1985 if (!*args[2]) {
1986 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1987 file, linenum, args[0]);
1988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
1990 }
1991
1992 err = invalid_char(args[1]);
1993 if (err) {
1994 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1995 file, linenum, *err, args[1]);
1996 err_code |= ERR_ALERT | ERR_FATAL;
1997 goto out;
1998 }
1999
2000 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2001 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2002 err_code |= ERR_ALERT | ERR_ABORT;
2003 goto out;
2004 }
2005
2006 /* the mailers are linked backwards first */
2007 curmailers->count++;
2008 newmailer->next = curmailers->mailer_list;
2009 curmailers->mailer_list = newmailer;
2010 newmailer->mailers = curmailers;
2011 newmailer->conf.file = strdup(file);
2012 newmailer->conf.line = linenum;
2013
2014 newmailer->id = strdup(args[1]);
2015
2016 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2017 if (!sk) {
2018 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
2021 }
2022
2023 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002024 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2025 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002026 file, linenum, args[0], args[1]);
2027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
2029 }
2030
2031 if (port1 != port2) {
2032 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2033 file, linenum, args[0], args[1], args[2]);
2034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
2036 }
2037
2038 if (!port1) {
2039 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2040 file, linenum, args[0], args[1], args[2]);
2041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
2043 }
2044
2045 newmailer->addr = *sk;
2046 newmailer->proto = proto;
2047 newmailer->xprt = &raw_sock;
2048 newmailer->sock_init_arg = NULL;
2049 } /* neither "mailer" nor "mailers" */
2050 else if (*args[0] != 0) {
2051 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
2054 }
2055
2056out:
2057 free(errmsg);
2058 return err_code;
2059}
2060
Simon Horman9dc49962015-01-30 11:22:59 +09002061static void free_email_alert(struct proxy *p)
2062{
2063 free(p->email_alert.mailers.name);
2064 p->email_alert.mailers.name = NULL;
2065 free(p->email_alert.from);
2066 p->email_alert.from = NULL;
2067 free(p->email_alert.to);
2068 p->email_alert.to = NULL;
2069 free(p->email_alert.myhostname);
2070 p->email_alert.myhostname = NULL;
2071}
2072
Willy Tarreau3842f002009-06-14 11:39:52 +02002073int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002074{
2075 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002076 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002077 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002078 int rc;
2079 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002080 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002081 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002082 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002083 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002084 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002085
Willy Tarreau977b8e42006-12-29 14:19:17 +01002086 if (!strcmp(args[0], "listen"))
2087 rc = PR_CAP_LISTEN;
2088 else if (!strcmp(args[0], "frontend"))
2089 rc = PR_CAP_FE | PR_CAP_RS;
2090 else if (!strcmp(args[0], "backend"))
2091 rc = PR_CAP_BE | PR_CAP_RS;
2092 else if (!strcmp(args[0], "ruleset"))
2093 rc = PR_CAP_RS;
2094 else
2095 rc = PR_CAP_NONE;
2096
2097 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002098 struct ebpt_node *node;
2099
Willy Tarreaubaaee002006-06-26 02:48:02 +02002100 if (!*args[1]) {
2101 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2102 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2103 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_ABORT;
2105 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002106 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002107
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002108 err = invalid_char(args[1]);
2109 if (err) {
2110 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2111 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002112 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002113 }
2114
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002115 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2116 curproxy = container_of(node, struct proxy, conf.by_name);
2117
2118 if (strcmp(curproxy->id, args[1]) != 0)
2119 break;
2120
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002121 /*
2122 * If there are two proxies with the same name only following
2123 * combinations are allowed:
2124 *
2125 * listen backend frontend ruleset
2126 * listen - - - -
2127 * backend - - OK -
2128 * frontend - OK - -
2129 * ruleset - - - -
2130 */
2131
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002132 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2133 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002134 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2135 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2136 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002137 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002138 }
2139 }
2140
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002143 err_code |= ERR_ALERT | ERR_ABORT;
2144 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002146
Willy Tarreau97cb7802010-01-03 20:23:58 +01002147 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148 curproxy->next = proxy;
2149 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002150 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2151 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002152 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002153 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002154 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002155 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002156
2157 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002158 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002159 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002160
Willy Tarreau4348fad2012-09-20 16:48:07 +02002161 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2162
Willy Tarreau902636f2013-03-10 19:44:48 +01002163 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2164 if (errmsg && *errmsg) {
2165 indent_msg(&errmsg, 2);
2166 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002167 }
2168 else
2169 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2170 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002171 err_code |= ERR_FATAL;
2172 goto out;
2173 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002174
Willy Tarreau4348fad2012-09-20 16:48:07 +02002175 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002176 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 }
2179
2180 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002181 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002182 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002183
Willy Tarreaubaaee002006-06-26 02:48:02 +02002184 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002185 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002186 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002187 curproxy->no_options = defproxy.no_options;
2188 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002189 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002190 curproxy->except_net = defproxy.except_net;
2191 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002192 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002193 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002194
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002195 if (defproxy.fwdfor_hdr_len) {
2196 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2197 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2198 }
2199
Willy Tarreaub86db342009-11-30 11:50:16 +01002200 if (defproxy.orgto_hdr_len) {
2201 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2202 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2203 }
2204
Mark Lamourinec2247f02012-01-04 13:02:01 -05002205 if (defproxy.server_id_hdr_len) {
2206 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2207 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2208 }
2209
Willy Tarreau977b8e42006-12-29 14:19:17 +01002210 if (curproxy->cap & PR_CAP_FE) {
2211 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002212 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002213 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214
2215 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002216 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2217 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002218
2219 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2220 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002221
Willy Tarreau977b8e42006-12-29 14:19:17 +01002222 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002223 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224 curproxy->fullconn = defproxy.fullconn;
2225 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002226 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002227
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002228 if (defproxy.check_req) {
2229 curproxy->check_req = calloc(1, defproxy.check_len);
2230 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2231 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002232 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002233
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002234 if (defproxy.expect_str) {
2235 curproxy->expect_str = strdup(defproxy.expect_str);
2236 if (defproxy.expect_regex) {
2237 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002238 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2239 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002240 }
2241 }
2242
Willy Tarreau67402132012-05-31 20:40:20 +02002243 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002244 if (defproxy.cookie_name)
2245 curproxy->cookie_name = strdup(defproxy.cookie_name);
2246 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002247 if (defproxy.cookie_domain)
2248 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002249
Willy Tarreau31936852010-10-06 16:59:56 +02002250 if (defproxy.cookie_maxidle)
2251 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2252
2253 if (defproxy.cookie_maxlife)
2254 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2255
Emeric Brun647caf12009-06-30 17:57:00 +02002256 if (defproxy.rdp_cookie_name)
2257 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2258 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2259
Willy Tarreau01732802007-11-01 22:48:15 +01002260 if (defproxy.url_param_name)
2261 curproxy->url_param_name = strdup(defproxy.url_param_name);
2262 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002263
Benoitaffb4812009-03-25 13:02:10 +01002264 if (defproxy.hh_name)
2265 curproxy->hh_name = strdup(defproxy.hh_name);
2266 curproxy->hh_len = defproxy.hh_len;
2267 curproxy->hh_match_domain = defproxy.hh_match_domain;
2268
Willy Tarreauef9a3602012-12-08 22:29:20 +01002269 if (defproxy.conn_src.iface_name)
2270 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2271 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002272 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002273#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002274 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002275#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002278 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002279 if (defproxy.capture_name)
2280 curproxy->capture_name = strdup(defproxy.capture_name);
2281 curproxy->capture_namelen = defproxy.capture_namelen;
2282 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002284
Willy Tarreau977b8e42006-12-29 14:19:17 +01002285 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002286 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002287 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002288 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002289 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002290 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002291 curproxy->mon_net = defproxy.mon_net;
2292 curproxy->mon_mask = defproxy.mon_mask;
2293 if (defproxy.monitor_uri)
2294 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2295 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002296 if (defproxy.defbe.name)
2297 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002298
2299 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002300 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2301 if (curproxy->conf.logformat_string &&
2302 curproxy->conf.logformat_string != default_http_log_format &&
2303 curproxy->conf.logformat_string != default_tcp_log_format &&
2304 curproxy->conf.logformat_string != clf_http_log_format)
2305 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2306
2307 if (defproxy.conf.lfs_file) {
2308 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2309 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2310 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002311 }
2312
2313 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002314 curproxy->timeout.connect = defproxy.timeout.connect;
2315 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002316 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002317 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002318 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002319 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002320 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002321 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002322 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002323 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002324 }
2325
Willy Tarreaubaaee002006-06-26 02:48:02 +02002326 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002327 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002328
2329 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002330 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002331 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002332 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002333 LIST_INIT(&node->list);
2334 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2335 }
2336
Willy Tarreau62a61232013-04-12 18:13:46 +02002337 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2338 if (curproxy->conf.uniqueid_format_string)
2339 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2340
Willy Tarreau094af4e2015-01-07 15:03:42 +01002341 if (defproxy.log_tag)
2342 curproxy->log_tag = strdup(defproxy.log_tag);
2343
Willy Tarreau62a61232013-04-12 18:13:46 +02002344 if (defproxy.conf.uif_file) {
2345 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2346 curproxy->conf.uif_line = defproxy.conf.uif_line;
2347 }
William Lallemanda73203e2012-03-12 12:48:57 +01002348
2349 /* copy default header unique id */
2350 if (defproxy.header_unique_id)
2351 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2352
William Lallemand82fe75c2012-10-23 10:25:10 +02002353 /* default compression options */
2354 if (defproxy.comp != NULL) {
2355 curproxy->comp = calloc(1, sizeof(struct comp));
2356 curproxy->comp->algos = defproxy.comp->algos;
2357 curproxy->comp->types = defproxy.comp->types;
2358 }
2359
Willy Tarreaubaaee002006-06-26 02:48:02 +02002360 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002361 curproxy->conf.used_listener_id = EB_ROOT;
2362 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002363
Simon Horman98637e52014-06-20 12:30:16 +09002364 if (defproxy.check_path)
2365 curproxy->check_path = strdup(defproxy.check_path);
2366 if (defproxy.check_command)
2367 curproxy->check_command = strdup(defproxy.check_command);
2368
Simon Horman9dc49962015-01-30 11:22:59 +09002369 if (defproxy.email_alert.mailers.name)
2370 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2371 if (defproxy.email_alert.from)
2372 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2373 if (defproxy.email_alert.to)
2374 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2375 if (defproxy.email_alert.myhostname)
2376 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002377 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002378
Willy Tarreau93893792009-07-23 13:19:11 +02002379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 }
2381 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2382 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002383 /* FIXME-20070101: we should do this too at the end of the
2384 * config parsing to free all default values.
2385 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002387 free(defproxy.check_command);
2388 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002389 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002390 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002391 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002392 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002393 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002394 free(defproxy.capture_name);
2395 free(defproxy.monitor_uri);
2396 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002397 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002398 free(defproxy.fwdfor_hdr_name);
2399 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002400 free(defproxy.orgto_hdr_name);
2401 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002402 free(defproxy.server_id_hdr_name);
2403 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002404 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002405 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002406 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002407 free(defproxy.expect_regex);
2408 defproxy.expect_regex = NULL;
2409 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002410
Willy Tarreau62a61232013-04-12 18:13:46 +02002411 if (defproxy.conf.logformat_string != default_http_log_format &&
2412 defproxy.conf.logformat_string != default_tcp_log_format &&
2413 defproxy.conf.logformat_string != clf_http_log_format)
2414 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002415
Willy Tarreau62a61232013-04-12 18:13:46 +02002416 free(defproxy.conf.uniqueid_format_string);
2417 free(defproxy.conf.lfs_file);
2418 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002419 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002420 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002421
Willy Tarreaua534fea2008-08-03 12:19:50 +02002422 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002423 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002424
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 /* we cannot free uri_auth because it might already be used */
2426 init_default_instance();
2427 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002428 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2429 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002430 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002432 }
2433 else if (curproxy == NULL) {
2434 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002437 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002438
2439 /* update the current file and line being parsed */
2440 curproxy->conf.args.file = curproxy->conf.file;
2441 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002442
2443 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002444 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2445 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2446 if (err_code & ERR_FATAL)
2447 goto out;
2448 }
2449 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002450 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002451 int cur_arg;
2452
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453 if (curproxy == &defproxy) {
2454 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002455 err_code |= ERR_ALERT | ERR_FATAL;
2456 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002457 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002458 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002459 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002460
Willy Tarreau24709282013-03-10 21:32:12 +01002461 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002462 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002463 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002464 err_code |= ERR_ALERT | ERR_FATAL;
2465 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002466 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002467
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002468 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002469
2470 /* use default settings for unix sockets */
2471 bind_conf->ux.uid = global.unix_bind.ux.uid;
2472 bind_conf->ux.gid = global.unix_bind.ux.gid;
2473 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002474
2475 /* NOTE: the following line might create several listeners if there
2476 * are comma-separated IPs or port ranges. So all further processing
2477 * will have to be applied to all listeners created after last_listen.
2478 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002479 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2480 if (errmsg && *errmsg) {
2481 indent_msg(&errmsg, 2);
2482 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002483 }
2484 else
2485 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2486 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002490
Willy Tarreau4348fad2012-09-20 16:48:07 +02002491 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2492 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002493 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002494 }
2495
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002496 cur_arg = 2;
2497 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002498 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002499 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002500 char *err;
2501
Willy Tarreau26982662012-09-12 23:17:10 +02002502 kw = bind_find_kw(args[cur_arg]);
2503 if (kw) {
2504 char *err = NULL;
2505 int code;
2506
2507 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002508 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2509 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002510 cur_arg += 1 + kw->skip ;
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514
Willy Tarreau4348fad2012-09-20 16:48:07 +02002515 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002516 err_code |= code;
2517
2518 if (code) {
2519 if (err && *err) {
2520 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002521 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002522 }
2523 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002524 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2525 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002526 if (code & ERR_FATAL) {
2527 free(err);
2528 cur_arg += 1 + kw->skip;
2529 goto out;
2530 }
2531 }
2532 free(err);
2533 cur_arg += 1 + kw->skip;
2534 continue;
2535 }
2536
Willy Tarreau8638f482012-09-18 18:01:17 +02002537 err = NULL;
2538 if (!bind_dumped) {
2539 bind_dump_kws(&err);
2540 indent_msg(&err, 4);
2541 bind_dumped = 1;
2542 }
2543
2544 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2545 file, linenum, args[0], args[1], args[cur_arg],
2546 err ? " Registered keywords :" : "", err ? err : "");
2547 free(err);
2548
Willy Tarreau93893792009-07-23 13:19:11 +02002549 err_code |= ERR_ALERT | ERR_FATAL;
2550 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002551 }
Willy Tarreau93893792009-07-23 13:19:11 +02002552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
2554 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002555 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2557 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002558 err_code |= ERR_ALERT | ERR_FATAL;
2559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002561 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002562 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002563
Willy Tarreaubaaee002006-06-26 02:48:02 +02002564 /* flush useless bits */
2565 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002566 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002567 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002568 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002570 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002571
Willy Tarreau1c47f852006-07-09 08:22:27 +02002572 if (!*args[1]) {
2573 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2574 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002575 err_code |= ERR_ALERT | ERR_FATAL;
2576 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002577 }
2578
Willy Tarreaua534fea2008-08-03 12:19:50 +02002579 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002580 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002581 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002582 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002583 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2584
Willy Tarreau93893792009-07-23 13:19:11 +02002585 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2588 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2589 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2590 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2591 else {
2592 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002593 err_code |= ERR_ALERT | ERR_FATAL;
2594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595 }
2596 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002597 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002598 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002599
2600 if (curproxy == &defproxy) {
2601 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002605 }
2606
2607 if (!*args[1]) {
2608 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2609 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002612 }
2613
2614 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002615 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002616
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002617 if (curproxy->uuid <= 0) {
2618 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002619 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002620 err_code |= ERR_ALERT | ERR_FATAL;
2621 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002622 }
2623
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002624 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2625 if (node) {
2626 struct proxy *target = container_of(node, struct proxy, conf.id);
2627 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2628 file, linenum, proxy_type_str(curproxy), curproxy->id,
2629 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002634 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002635 else if (!strcmp(args[0], "description")) {
2636 int i, len=0;
2637 char *d;
2638
Cyril Bonté99ed3272010-01-24 23:29:44 +01002639 if (curproxy == &defproxy) {
2640 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2641 file, linenum, args[0]);
2642 err_code |= ERR_ALERT | ERR_FATAL;
2643 goto out;
2644 }
2645
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002646 if (!*args[1]) {
2647 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2648 file, linenum, args[0]);
2649 return -1;
2650 }
2651
Willy Tarreau348acfe2014-04-14 15:00:39 +02002652 for (i = 1; *args[i]; i++)
2653 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002654
2655 d = (char *)calloc(1, len);
2656 curproxy->desc = d;
2657
Willy Tarreau348acfe2014-04-14 15:00:39 +02002658 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2659 for (i = 2; *args[i]; i++)
2660 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002661
2662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002663 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2664 curproxy->state = PR_STSTOPPED;
2665 }
2666 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2667 curproxy->state = PR_STNEW;
2668 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002669 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2670 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002671 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002672
2673 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002674 unsigned int low, high;
2675
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002676 if (strcmp(args[cur_arg], "all") == 0) {
2677 set = 0;
2678 break;
2679 }
2680 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002681 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002682 }
2683 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002684 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002685 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002686 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002687 char *dash = strchr(args[cur_arg], '-');
2688
2689 low = high = str2uic(args[cur_arg]);
2690 if (dash)
2691 high = str2uic(dash + 1);
2692
2693 if (high < low) {
2694 unsigned int swap = low;
2695 low = high;
2696 high = swap;
2697 }
2698
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002699 if (low < 1 || high > LONGBITS) {
2700 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2701 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002702 err_code |= ERR_ALERT | ERR_FATAL;
2703 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002704 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002705 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002706 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002707 }
2708 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002709 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2710 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002711 err_code |= ERR_ALERT | ERR_FATAL;
2712 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002713 }
2714 cur_arg++;
2715 }
2716 curproxy->bind_proc = set;
2717 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002718 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002719 if (curproxy == &defproxy) {
2720 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
2722 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002723 }
2724
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002725 err = invalid_char(args[1]);
2726 if (err) {
2727 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2728 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002729 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002730 }
2731
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002732 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002733 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2734 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_ALERT | ERR_FATAL;
2736 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002737 }
2738 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002739 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2740 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002741
Willy Tarreau977b8e42006-12-29 14:19:17 +01002742 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002743 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744
Willy Tarreaubaaee002006-06-26 02:48:02 +02002745 if (*(args[1]) == 0) {
2746 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2747 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002748 err_code |= ERR_ALERT | ERR_FATAL;
2749 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002750 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002751
Willy Tarreau67402132012-05-31 20:40:20 +02002752 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002753 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002754 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002755 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 curproxy->cookie_name = strdup(args[1]);
2757 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002758
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 cur_arg = 2;
2760 while (*(args[cur_arg])) {
2761 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002762 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002763 }
2764 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002765 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002766 }
2767 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002768 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002769 }
2770 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002771 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 }
2773 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002774 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002775 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002776 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002777 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002779 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002780 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002782 else if (!strcmp(args[cur_arg], "httponly")) {
2783 curproxy->ck_opts |= PR_CK_HTTPONLY;
2784 }
2785 else if (!strcmp(args[cur_arg], "secure")) {
2786 curproxy->ck_opts |= PR_CK_SECURE;
2787 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002788 else if (!strcmp(args[cur_arg], "domain")) {
2789 if (!*args[cur_arg + 1]) {
2790 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2791 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002792 err_code |= ERR_ALERT | ERR_FATAL;
2793 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002794 }
2795
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002796 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002797 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002798 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2799 " dots nor does not start with a dot."
2800 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002801 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002802 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002803 }
2804
2805 err = invalid_domainchar(args[cur_arg + 1]);
2806 if (err) {
2807 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2808 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002809 err_code |= ERR_ALERT | ERR_FATAL;
2810 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002811 }
2812
Willy Tarreau68a897b2009-12-03 23:28:34 +01002813 if (!curproxy->cookie_domain) {
2814 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2815 } else {
2816 /* one domain was already specified, add another one by
2817 * building the string which will be returned along with
2818 * the cookie.
2819 */
2820 char *new_ptr;
2821 int new_len = strlen(curproxy->cookie_domain) +
2822 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2823 new_ptr = malloc(new_len);
2824 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2825 free(curproxy->cookie_domain);
2826 curproxy->cookie_domain = new_ptr;
2827 }
Willy Tarreau31936852010-10-06 16:59:56 +02002828 cur_arg++;
2829 }
2830 else if (!strcmp(args[cur_arg], "maxidle")) {
2831 unsigned int maxidle;
2832 const char *res;
2833
2834 if (!*args[cur_arg + 1]) {
2835 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2836 file, linenum, args[cur_arg]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840
2841 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2842 if (res) {
2843 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2844 file, linenum, *res, args[cur_arg]);
2845 err_code |= ERR_ALERT | ERR_FATAL;
2846 goto out;
2847 }
2848 curproxy->cookie_maxidle = maxidle;
2849 cur_arg++;
2850 }
2851 else if (!strcmp(args[cur_arg], "maxlife")) {
2852 unsigned int maxlife;
2853 const char *res;
2854
2855 if (!*args[cur_arg + 1]) {
2856 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2857 file, linenum, args[cur_arg]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861
2862 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2863 if (res) {
2864 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2865 file, linenum, *res, args[cur_arg]);
2866 err_code |= ERR_ALERT | ERR_FATAL;
2867 goto out;
2868 }
2869 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002870 cur_arg++;
2871 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002872 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002873 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 +02002874 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002875 err_code |= ERR_ALERT | ERR_FATAL;
2876 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 }
2878 cur_arg++;
2879 }
Willy Tarreau67402132012-05-31 20:40:20 +02002880 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002881 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2882 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002883 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002884 }
2885
Willy Tarreau67402132012-05-31 20:40:20 +02002886 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002887 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2888 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002889 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002891
Willy Tarreau67402132012-05-31 20:40:20 +02002892 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002893 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2894 file, linenum);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002898 else if (!strcmp(args[0], "email-alert")) {
2899 if (*(args[1]) == 0) {
2900 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2901 file, linenum, args[0]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905
2906 if (!strcmp(args[1], "from")) {
2907 if (*(args[1]) == 0) {
2908 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2909 file, linenum, args[1]);
2910 err_code |= ERR_ALERT | ERR_FATAL;
2911 goto out;
2912 }
2913 free(curproxy->email_alert.from);
2914 curproxy->email_alert.from = strdup(args[2]);
2915 }
2916 else if (!strcmp(args[1], "mailers")) {
2917 if (*(args[1]) == 0) {
2918 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2919 file, linenum, args[1]);
2920 err_code |= ERR_ALERT | ERR_FATAL;
2921 goto out;
2922 }
2923 free(curproxy->email_alert.mailers.name);
2924 curproxy->email_alert.mailers.name = strdup(args[2]);
2925 }
2926 else if (!strcmp(args[1], "myhostname")) {
2927 if (*(args[1]) == 0) {
2928 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2929 file, linenum, args[1]);
2930 err_code |= ERR_ALERT | ERR_FATAL;
2931 goto out;
2932 }
2933 free(curproxy->email_alert.myhostname);
2934 curproxy->email_alert.myhostname = strdup(args[2]);
2935 }
Simon Horman64e34162015-02-06 11:11:57 +09002936 else if (!strcmp(args[1], "level")) {
2937 curproxy->email_alert.level = get_log_level(args[2]);
2938 if (curproxy->email_alert.level < 0) {
2939 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2940 file, linenum, args[1], args[2]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
2944 }
Simon Horman9dc49962015-01-30 11:22:59 +09002945 else if (!strcmp(args[1], "to")) {
2946 if (*(args[1]) == 0) {
2947 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2948 file, linenum, args[1]);
2949 err_code |= ERR_ALERT | ERR_FATAL;
2950 goto out;
2951 }
2952 free(curproxy->email_alert.to);
2953 curproxy->email_alert.to = strdup(args[2]);
2954 }
2955 else {
2956 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2957 file, linenum, args[1]);
2958 err_code |= ERR_ALERT | ERR_FATAL;
2959 goto out;
2960 }
Simon Horman64e34162015-02-06 11:11:57 +09002961 /* Indicate that the email_alert is at least partially configured */
2962 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002963 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002964 else if (!strcmp(args[0], "external-check")) {
2965 if (*(args[1]) == 0) {
2966 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2967 file, linenum, args[0]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971
2972 if (!strcmp(args[1], "command")) {
2973 if (*(args[1]) == 0) {
2974 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2975 file, linenum, args[1]);
2976 err_code |= ERR_ALERT | ERR_FATAL;
2977 goto out;
2978 }
2979 free(curproxy->check_command);
2980 curproxy->check_command = strdup(args[2]);
2981 }
2982 else if (!strcmp(args[1], "path")) {
2983 if (*(args[1]) == 0) {
2984 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2985 file, linenum, args[1]);
2986 err_code |= ERR_ALERT | ERR_FATAL;
2987 goto out;
2988 }
2989 free(curproxy->check_path);
2990 curproxy->check_path = strdup(args[2]);
2991 }
2992 else {
2993 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2994 file, linenum, args[1]);
2995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
2997 }
2998 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002999 else if (!strcmp(args[0], "persist")) { /* persist */
3000 if (*(args[1]) == 0) {
3001 Alert("parsing [%s:%d] : missing persist method.\n",
3002 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003003 err_code |= ERR_ALERT | ERR_FATAL;
3004 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003005 }
3006
3007 if (!strncmp(args[1], "rdp-cookie", 10)) {
3008 curproxy->options2 |= PR_O2_RDPC_PRST;
3009
Emeric Brunb982a3d2010-01-04 15:45:53 +01003010 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003011 const char *beg, *end;
3012
3013 beg = args[1] + 11;
3014 end = strchr(beg, ')');
3015
3016 if (!end || end == beg) {
3017 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3018 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003019 err_code |= ERR_ALERT | ERR_FATAL;
3020 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003021 }
3022
3023 free(curproxy->rdp_cookie_name);
3024 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3025 curproxy->rdp_cookie_len = end-beg;
3026 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003027 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003028 free(curproxy->rdp_cookie_name);
3029 curproxy->rdp_cookie_name = strdup("msts");
3030 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3031 }
3032 else { /* syntax */
3033 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3034 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003037 }
3038 }
3039 else {
3040 Alert("parsing [%s:%d] : unknown persist method.\n",
3041 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003042 err_code |= ERR_ALERT | ERR_FATAL;
3043 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003044 }
3045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003047 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003049 if (curproxy == &defproxy) {
3050 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3051 err_code |= ERR_ALERT | ERR_FATAL;
3052 goto out;
3053 }
3054
Willy Tarreau977b8e42006-12-29 14:19:17 +01003055 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003056 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003057
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003059 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003060 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003061 err_code |= ERR_ALERT | ERR_FATAL;
3062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003063 }
3064 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003065 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 curproxy->appsession_name = strdup(args[1]);
3067 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3068 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003069 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3070 if (err) {
3071 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3072 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_FATAL;
3074 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003075 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003076 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003077
Willy Tarreau51041c72007-09-09 21:56:53 +02003078 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3079 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003080 err_code |= ERR_ALERT | ERR_ABORT;
3081 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003082 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003083
3084 cur_arg = 6;
3085 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003086 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3087 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003088 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003089 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003090 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003091 } else if (!strcmp(args[cur_arg], "prefix")) {
3092 curproxy->options2 |= PR_O2_AS_PFX;
3093 } else if (!strcmp(args[cur_arg], "mode")) {
3094 if (!*args[cur_arg + 1]) {
3095 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3096 file, linenum, args[0], args[cur_arg]);
3097 err_code |= ERR_ALERT | ERR_FATAL;
3098 goto out;
3099 }
3100
3101 cur_arg++;
3102 if (!strcmp(args[cur_arg], "query-string")) {
3103 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3104 curproxy->options2 |= PR_O2_AS_M_QS;
3105 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3106 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3107 curproxy->options2 |= PR_O2_AS_M_PP;
3108 } else {
3109 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
3112 }
3113 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003114 cur_arg++;
3115 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 } /* Url App Session */
3117 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003118 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003119 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003120
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003122 if (curproxy == &defproxy) {
3123 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
3126 }
3127
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 if (*(args[4]) == 0) {
3129 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3130 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003131 err_code |= ERR_ALERT | ERR_FATAL;
3132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003133 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003134 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 curproxy->capture_name = strdup(args[2]);
3136 curproxy->capture_namelen = strlen(curproxy->capture_name);
3137 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 curproxy->to_log |= LW_COOKIE;
3139 }
3140 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3141 struct cap_hdr *hdr;
3142
3143 if (curproxy == &defproxy) {
3144 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 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148
3149 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3150 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3151 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
3155
3156 hdr = calloc(sizeof(struct cap_hdr), 1);
3157 hdr->next = curproxy->req_cap;
3158 hdr->name = strdup(args[3]);
3159 hdr->namelen = strlen(args[3]);
3160 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003161 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 hdr->index = curproxy->nb_req_cap++;
3163 curproxy->req_cap = hdr;
3164 curproxy->to_log |= LW_REQHDR;
3165 }
3166 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3167 struct cap_hdr *hdr;
3168
3169 if (curproxy == &defproxy) {
3170 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 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174
3175 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3176 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3177 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003178 err_code |= ERR_ALERT | ERR_FATAL;
3179 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 }
3181 hdr = calloc(sizeof(struct cap_hdr), 1);
3182 hdr->next = curproxy->rsp_cap;
3183 hdr->name = strdup(args[3]);
3184 hdr->namelen = strlen(args[3]);
3185 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003186 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 hdr->index = curproxy->nb_rsp_cap++;
3188 curproxy->rsp_cap = hdr;
3189 curproxy->to_log |= LW_RSPHDR;
3190 }
3191 else {
3192 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3193 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003198 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003199 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003200 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003201
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 if (*(args[1]) == 0) {
3203 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3204 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003205 err_code |= ERR_ALERT | ERR_FATAL;
3206 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003207 }
3208 curproxy->conn_retries = atol(args[1]);
3209 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003210 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003211 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003212
3213 if (curproxy == &defproxy) {
3214 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3215 err_code |= ERR_ALERT | ERR_FATAL;
3216 goto out;
3217 }
3218
Willy Tarreau20b0de52012-12-24 15:45:22 +01003219 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3220 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3221 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3222 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003223 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003224 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3225 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 +01003226 file, linenum, args[0]);
3227 err_code |= ERR_WARN;
3228 }
3229
Willy Tarreauff011f22011-01-06 17:51:27 +01003230 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003231
Willy Tarreauff011f22011-01-06 17:51:27 +01003232 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003233 err_code |= ERR_ALERT | ERR_ABORT;
3234 goto out;
3235 }
3236
Willy Tarreau5002f572014-04-23 01:32:02 +02003237 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003238 err_code |= warnif_cond_conflicts(rule->cond,
3239 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3240 file, linenum);
3241
Willy Tarreauff011f22011-01-06 17:51:27 +01003242 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003243 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003244 else if (!strcmp(args[0], "http-response")) { /* response access control */
3245 struct http_res_rule *rule;
3246
3247 if (curproxy == &defproxy) {
3248 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3249 err_code |= ERR_ALERT | ERR_FATAL;
3250 goto out;
3251 }
3252
3253 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3254 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3255 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3256 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3257 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3258 file, linenum, args[0]);
3259 err_code |= ERR_WARN;
3260 }
3261
3262 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3263
3264 if (!rule) {
3265 err_code |= ERR_ALERT | ERR_ABORT;
3266 goto out;
3267 }
3268
3269 err_code |= warnif_cond_conflicts(rule->cond,
3270 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3271 file, linenum);
3272
3273 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3274 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003275 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3276 /* set the header name and length into the proxy structure */
3277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3278 err_code |= ERR_WARN;
3279
3280 if (!*args[1]) {
3281 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3282 file, linenum, args[0]);
3283 err_code |= ERR_ALERT | ERR_FATAL;
3284 goto out;
3285 }
3286
3287 /* set the desired header name */
3288 free(curproxy->server_id_hdr_name);
3289 curproxy->server_id_hdr_name = strdup(args[1]);
3290 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3291 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003292 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003293 struct http_req_rule *rule;
3294
Willy Tarreaub099aca2008-10-12 17:26:37 +02003295 if (curproxy == &defproxy) {
3296 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003297 err_code |= ERR_ALERT | ERR_FATAL;
3298 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003299 }
3300
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003301 /* emulate "block" using "http-request block". Since these rules are supposed to
3302 * be processed before all http-request rules, we put them into their own list
3303 * and will insert them at the end.
3304 */
3305 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3306 if (!rule) {
3307 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003308 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003309 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003310 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3311 err_code |= warnif_cond_conflicts(rule->cond,
3312 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3313 file, linenum);
3314 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003315
3316 if (!already_warned(WARN_BLOCK_DEPRECATED))
3317 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]);
3318
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003319 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003320 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003321 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003322
Cyril Bonté99ed3272010-01-24 23:29:44 +01003323 if (curproxy == &defproxy) {
3324 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
3327 }
3328
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003329 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003330 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3331 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003332 err_code |= ERR_ALERT | ERR_FATAL;
3333 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003334 }
3335
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003336 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003337 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003338 err_code |= warnif_cond_conflicts(rule->cond,
3339 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3340 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003341 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003342 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003343 struct switching_rule *rule;
3344
Willy Tarreaub099aca2008-10-12 17:26:37 +02003345 if (curproxy == &defproxy) {
3346 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003349 }
3350
Willy Tarreau55ea7572007-06-17 19:56:27 +02003351 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003353
3354 if (*(args[1]) == 0) {
3355 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003358 }
3359
Willy Tarreauf51658d2014-04-23 01:21:56 +02003360 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3361 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3362 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3363 file, linenum, errmsg);
3364 err_code |= ERR_ALERT | ERR_FATAL;
3365 goto out;
3366 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003367
Willy Tarreauf51658d2014-04-23 01:21:56 +02003368 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003369 }
3370
3371 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3372 rule->cond = cond;
3373 rule->be.name = strdup(args[1]);
3374 LIST_INIT(&rule->list);
3375 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3376 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003377 else if (strcmp(args[0], "use-server") == 0) {
3378 struct server_rule *rule;
3379
3380 if (curproxy == &defproxy) {
3381 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3382 err_code |= ERR_ALERT | ERR_FATAL;
3383 goto out;
3384 }
3385
3386 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3387 err_code |= ERR_WARN;
3388
3389 if (*(args[1]) == 0) {
3390 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
3395 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3396 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3397 file, linenum, args[0]);
3398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003402 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3403 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3404 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
3407 }
3408
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003409 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003410
3411 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3412 rule->cond = cond;
3413 rule->srv.name = strdup(args[1]);
3414 LIST_INIT(&rule->list);
3415 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3416 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3417 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003418 else if ((!strcmp(args[0], "force-persist")) ||
3419 (!strcmp(args[0], "ignore-persist"))) {
3420 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003421
3422 if (curproxy == &defproxy) {
3423 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3424 err_code |= ERR_ALERT | ERR_FATAL;
3425 goto out;
3426 }
3427
3428 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3429 err_code |= ERR_WARN;
3430
Willy Tarreauef6494c2010-01-28 17:12:36 +01003431 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003432 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3433 file, linenum, args[0]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003438 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3439 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3440 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003441 err_code |= ERR_ALERT | ERR_FATAL;
3442 goto out;
3443 }
3444
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003445 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3446 * where force-persist is applied.
3447 */
3448 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003449
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003450 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003451 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003452 if (!strcmp(args[0], "force-persist")) {
3453 rule->type = PERSIST_TYPE_FORCE;
3454 } else {
3455 rule->type = PERSIST_TYPE_IGNORE;
3456 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003457 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003458 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003459 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003460 else if (!strcmp(args[0], "stick-table")) {
3461 int myidx = 1;
3462
Emeric Brun32da3c42010-09-23 18:39:19 +02003463 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003464 curproxy->table.type = (unsigned int)-1;
3465 while (*args[myidx]) {
3466 const char *err;
3467
3468 if (strcmp(args[myidx], "size") == 0) {
3469 myidx++;
3470 if (!*(args[myidx])) {
3471 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3472 file, linenum, args[myidx-1]);
3473 err_code |= ERR_ALERT | ERR_FATAL;
3474 goto out;
3475 }
3476 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3477 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3478 file, linenum, *err, args[myidx-1]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003482 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003483 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003484 else if (strcmp(args[myidx], "peers") == 0) {
3485 myidx++;
Godbach50523162013-12-11 19:48:57 +08003486 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003487 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3488 file, linenum, args[myidx-1]);
3489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Godbach50523162013-12-11 19:48:57 +08003491 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003492 curproxy->table.peers.name = strdup(args[myidx++]);
3493 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003494 else if (strcmp(args[myidx], "expire") == 0) {
3495 myidx++;
3496 if (!*(args[myidx])) {
3497 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3498 file, linenum, args[myidx-1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3503 if (err) {
3504 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3505 file, linenum, *err, args[myidx-1]);
3506 err_code |= ERR_ALERT | ERR_FATAL;
3507 goto out;
3508 }
3509 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003510 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003511 }
3512 else if (strcmp(args[myidx], "nopurge") == 0) {
3513 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003514 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003515 }
3516 else if (strcmp(args[myidx], "type") == 0) {
3517 myidx++;
3518 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3519 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3520 file, linenum, args[myidx]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003524 /* myidx already points to next arg */
3525 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003526 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003527 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003528 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003529
3530 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003531 nw = args[myidx];
3532 while (*nw) {
3533 /* the "store" keyword supports a comma-separated list */
3534 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003535 sa = NULL; /* store arg */
3536 while (*nw && *nw != ',') {
3537 if (*nw == '(') {
3538 *nw = 0;
3539 sa = ++nw;
3540 while (*nw != ')') {
3541 if (!*nw) {
3542 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3543 file, linenum, args[0], cw);
3544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
3546 }
3547 nw++;
3548 }
3549 *nw = '\0';
3550 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003551 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003552 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003553 if (*nw)
3554 *nw++ = '\0';
3555 type = stktable_get_data_type(cw);
3556 if (type < 0) {
3557 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3558 file, linenum, args[0], cw);
3559 err_code |= ERR_ALERT | ERR_FATAL;
3560 goto out;
3561 }
Willy Tarreauac782882010-06-20 10:41:54 +02003562
3563 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3564 switch (err) {
3565 case PE_NONE: break;
3566 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003567 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3568 file, linenum, args[0], cw);
3569 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003570 break;
3571
3572 case PE_ARG_MISSING:
3573 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3574 file, linenum, args[0], cw);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577
3578 case PE_ARG_NOT_USED:
3579 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3580 file, linenum, args[0], cw);
3581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
3583
3584 default:
3585 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3586 file, linenum, args[0], cw);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003589 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003590 }
3591 myidx++;
3592 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003593 else {
3594 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3595 file, linenum, args[myidx]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003598 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003599 }
3600
3601 if (!curproxy->table.size) {
3602 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3603 file, linenum);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607
3608 if (curproxy->table.type == (unsigned int)-1) {
3609 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3610 file, linenum);
3611 err_code |= ERR_ALERT | ERR_FATAL;
3612 goto out;
3613 }
3614 }
3615 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003616 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003617 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003618 int myidx = 0;
3619 const char *name = NULL;
3620 int flags;
3621
3622 if (curproxy == &defproxy) {
3623 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3624 err_code |= ERR_ALERT | ERR_FATAL;
3625 goto out;
3626 }
3627
3628 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3629 err_code |= ERR_WARN;
3630 goto out;
3631 }
3632
3633 myidx++;
3634 if ((strcmp(args[myidx], "store") == 0) ||
3635 (strcmp(args[myidx], "store-request") == 0)) {
3636 myidx++;
3637 flags = STK_IS_STORE;
3638 }
3639 else if (strcmp(args[myidx], "store-response") == 0) {
3640 myidx++;
3641 flags = STK_IS_STORE | STK_ON_RSP;
3642 }
3643 else if (strcmp(args[myidx], "match") == 0) {
3644 myidx++;
3645 flags = STK_IS_MATCH;
3646 }
3647 else if (strcmp(args[myidx], "on") == 0) {
3648 myidx++;
3649 flags = STK_IS_MATCH | STK_IS_STORE;
3650 }
3651 else {
3652 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3653 err_code |= ERR_ALERT | ERR_FATAL;
3654 goto out;
3655 }
3656
3657 if (*(args[myidx]) == 0) {
3658 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
3661 }
3662
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003663 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003664 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003665 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003666 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003667 err_code |= ERR_ALERT | ERR_FATAL;
3668 goto out;
3669 }
3670
3671 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003672 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3673 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3674 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003675 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003676 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003677 goto out;
3678 }
3679 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003680 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3681 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3682 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003683 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003684 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003685 goto out;
3686 }
3687 }
3688
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003689 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003690 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003691
Emeric Brunb982a3d2010-01-04 15:45:53 +01003692 if (strcmp(args[myidx], "table") == 0) {
3693 myidx++;
3694 name = args[myidx++];
3695 }
3696
Willy Tarreauef6494c2010-01-28 17:12:36 +01003697 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003698 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3699 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3700 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003701 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003702 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003703 goto out;
3704 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003705 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003706 else if (*(args[myidx])) {
3707 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3708 file, linenum, args[0], args[myidx]);
3709 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003710 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003711 goto out;
3712 }
Emeric Brun97679e72010-09-23 17:56:44 +02003713 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003714 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003715 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003716 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003717
Emeric Brunb982a3d2010-01-04 15:45:53 +01003718 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3719 rule->cond = cond;
3720 rule->expr = expr;
3721 rule->flags = flags;
3722 rule->table.name = name ? strdup(name) : NULL;
3723 LIST_INIT(&rule->list);
3724 if (flags & STK_ON_RSP)
3725 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3726 else
3727 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003729 else if (!strcmp(args[0], "stats")) {
3730 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3731 curproxy->uri_auth = NULL; /* we must detach from the default config */
3732
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003733 if (!*args[1]) {
3734 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003735 } else if (!strcmp(args[1], "admin")) {
3736 struct stats_admin_rule *rule;
3737
3738 if (curproxy == &defproxy) {
3739 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3740 err_code |= ERR_ALERT | ERR_FATAL;
3741 goto out;
3742 }
3743
3744 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3745 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3746 err_code |= ERR_ALERT | ERR_ABORT;
3747 goto out;
3748 }
3749
3750 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3751 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3752 file, linenum, args[0], args[1]);
3753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003756 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3757 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3758 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003759 err_code |= ERR_ALERT | ERR_FATAL;
3760 goto out;
3761 }
3762
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003763 err_code |= warnif_cond_conflicts(cond,
3764 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3765 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003766
3767 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3768 rule->cond = cond;
3769 LIST_INIT(&rule->list);
3770 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003771 } else if (!strcmp(args[1], "uri")) {
3772 if (*(args[2]) == 0) {
3773 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003774 err_code |= ERR_ALERT | ERR_FATAL;
3775 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003776 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3777 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003778 err_code |= ERR_ALERT | ERR_ABORT;
3779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003780 }
3781 } else if (!strcmp(args[1], "realm")) {
3782 if (*(args[2]) == 0) {
3783 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003786 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3787 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003788 err_code |= ERR_ALERT | ERR_ABORT;
3789 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003791 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003792 unsigned interval;
3793
3794 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3795 if (err) {
3796 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3797 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003798 err_code |= ERR_ALERT | ERR_FATAL;
3799 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003800 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3801 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003802 err_code |= ERR_ALERT | ERR_ABORT;
3803 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003804 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003805 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003806 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003807
3808 if (curproxy == &defproxy) {
3809 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813
3814 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3815 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3816 err_code |= ERR_ALERT | ERR_ABORT;
3817 goto out;
3818 }
3819
Willy Tarreauff011f22011-01-06 17:51:27 +01003820 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3821 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003822 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3823 file, linenum, args[0]);
3824 err_code |= ERR_WARN;
3825 }
3826
Willy Tarreauff011f22011-01-06 17:51:27 +01003827 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003828
Willy Tarreauff011f22011-01-06 17:51:27 +01003829 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003830 err_code |= ERR_ALERT | ERR_ABORT;
3831 goto out;
3832 }
3833
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003834 err_code |= warnif_cond_conflicts(rule->cond,
3835 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3836 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003837 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003838
Willy Tarreaubaaee002006-06-26 02:48:02 +02003839 } else if (!strcmp(args[1], "auth")) {
3840 if (*(args[2]) == 0) {
3841 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003842 err_code |= ERR_ALERT | ERR_FATAL;
3843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003844 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3845 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_ABORT;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
3849 } else if (!strcmp(args[1], "scope")) {
3850 if (*(args[2]) == 0) {
3851 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003852 err_code |= ERR_ALERT | ERR_FATAL;
3853 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003854 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3855 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003856 err_code |= ERR_ALERT | ERR_ABORT;
3857 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003858 }
3859 } else if (!strcmp(args[1], "enable")) {
3860 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3861 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_ABORT;
3863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003864 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003865 } else if (!strcmp(args[1], "hide-version")) {
3866 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3867 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003868 err_code |= ERR_ALERT | ERR_ABORT;
3869 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003870 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003871 } else if (!strcmp(args[1], "show-legends")) {
3872 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3873 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3874 err_code |= ERR_ALERT | ERR_ABORT;
3875 goto out;
3876 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003877 } else if (!strcmp(args[1], "show-node")) {
3878
3879 if (*args[2]) {
3880 int i;
3881 char c;
3882
3883 for (i=0; args[2][i]; i++) {
3884 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003885 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3886 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003887 break;
3888 }
3889
3890 if (!i || args[2][i]) {
3891 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3892 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3893 file, linenum, args[0], args[1]);
3894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
3896 }
3897 }
3898
3899 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3900 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3901 err_code |= ERR_ALERT | ERR_ABORT;
3902 goto out;
3903 }
3904 } else if (!strcmp(args[1], "show-desc")) {
3905 char *desc = NULL;
3906
3907 if (*args[2]) {
3908 int i, len=0;
3909 char *d;
3910
Willy Tarreau348acfe2014-04-14 15:00:39 +02003911 for (i = 2; *args[i]; i++)
3912 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003913
3914 desc = d = (char *)calloc(1, len);
3915
Willy Tarreau348acfe2014-04-14 15:00:39 +02003916 d += snprintf(d, desc + len - d, "%s", args[2]);
3917 for (i = 3; *args[i]; i++)
3918 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003919 }
3920
3921 if (!*args[2] && !global.desc)
3922 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3923 file, linenum, args[1]);
3924 else {
3925 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3926 free(desc);
3927 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3928 err_code |= ERR_ALERT | ERR_ABORT;
3929 goto out;
3930 }
3931 free(desc);
3932 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003933 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003934stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003935 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 +01003936 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003939 }
3940 }
3941 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003942 int optnum;
3943
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003944 if (*(args[1]) == '\0') {
3945 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3946 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_ALERT | ERR_FATAL;
3948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003949 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003950
3951 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3952 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003953 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3954 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3955 file, linenum, cfg_opts[optnum].name);
3956 err_code |= ERR_ALERT | ERR_FATAL;
3957 goto out;
3958 }
Willy Tarreau93893792009-07-23 13:19:11 +02003959 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3960 err_code |= ERR_WARN;
3961 goto out;
3962 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003963
Willy Tarreau3842f002009-06-14 11:39:52 +02003964 curproxy->no_options &= ~cfg_opts[optnum].val;
3965 curproxy->options &= ~cfg_opts[optnum].val;
3966
3967 switch (kwm) {
3968 case KWM_STD:
3969 curproxy->options |= cfg_opts[optnum].val;
3970 break;
3971 case KWM_NO:
3972 curproxy->no_options |= cfg_opts[optnum].val;
3973 break;
3974 case KWM_DEF: /* already cleared */
3975 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003976 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003977
Willy Tarreau93893792009-07-23 13:19:11 +02003978 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003979 }
3980 }
3981
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003982 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3983 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003984 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3985 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3986 file, linenum, cfg_opts2[optnum].name);
3987 err_code |= ERR_ALERT | ERR_FATAL;
3988 goto out;
3989 }
Willy Tarreau93893792009-07-23 13:19:11 +02003990 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3991 err_code |= ERR_WARN;
3992 goto out;
3993 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003994
Willy Tarreau3842f002009-06-14 11:39:52 +02003995 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3996 curproxy->options2 &= ~cfg_opts2[optnum].val;
3997
3998 switch (kwm) {
3999 case KWM_STD:
4000 curproxy->options2 |= cfg_opts2[optnum].val;
4001 break;
4002 case KWM_NO:
4003 curproxy->no_options2 |= cfg_opts2[optnum].val;
4004 break;
4005 case KWM_DEF: /* already cleared */
4006 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004007 }
Willy Tarreau93893792009-07-23 13:19:11 +02004008 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004009 }
4010 }
4011
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004012 /* HTTP options override each other. They can be cancelled using
4013 * "no option xxx" which only switches to default mode if the mode
4014 * was this one (useful for cancelling options set in defaults
4015 * sections).
4016 */
4017 if (strcmp(args[1], "httpclose") == 0) {
4018 if (kwm == KWM_STD) {
4019 curproxy->options &= ~PR_O_HTTP_MODE;
4020 curproxy->options |= PR_O_HTTP_PCL;
4021 goto out;
4022 }
4023 else if (kwm == KWM_NO) {
4024 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4025 curproxy->options &= ~PR_O_HTTP_MODE;
4026 goto out;
4027 }
4028 }
4029 else if (strcmp(args[1], "forceclose") == 0) {
4030 if (kwm == KWM_STD) {
4031 curproxy->options &= ~PR_O_HTTP_MODE;
4032 curproxy->options |= PR_O_HTTP_FCL;
4033 goto out;
4034 }
4035 else if (kwm == KWM_NO) {
4036 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4037 curproxy->options &= ~PR_O_HTTP_MODE;
4038 goto out;
4039 }
4040 }
4041 else if (strcmp(args[1], "http-server-close") == 0) {
4042 if (kwm == KWM_STD) {
4043 curproxy->options &= ~PR_O_HTTP_MODE;
4044 curproxy->options |= PR_O_HTTP_SCL;
4045 goto out;
4046 }
4047 else if (kwm == KWM_NO) {
4048 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4049 curproxy->options &= ~PR_O_HTTP_MODE;
4050 goto out;
4051 }
4052 }
4053 else if (strcmp(args[1], "http-keep-alive") == 0) {
4054 if (kwm == KWM_STD) {
4055 curproxy->options &= ~PR_O_HTTP_MODE;
4056 curproxy->options |= PR_O_HTTP_KAL;
4057 goto out;
4058 }
4059 else if (kwm == KWM_NO) {
4060 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4061 curproxy->options &= ~PR_O_HTTP_MODE;
4062 goto out;
4063 }
4064 }
4065 else if (strcmp(args[1], "http-tunnel") == 0) {
4066 if (kwm == KWM_STD) {
4067 curproxy->options &= ~PR_O_HTTP_MODE;
4068 curproxy->options |= PR_O_HTTP_TUN;
4069 goto out;
4070 }
4071 else if (kwm == KWM_NO) {
4072 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4073 curproxy->options &= ~PR_O_HTTP_MODE;
4074 goto out;
4075 }
4076 }
4077
Willy Tarreau3842f002009-06-14 11:39:52 +02004078 if (kwm != KWM_STD) {
4079 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004080 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004083 }
4084
Emeric Brun3a058f32009-06-30 18:26:00 +02004085 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004086 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004087 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004088 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004089 if (*(args[2]) != '\0') {
4090 if (!strcmp(args[2], "clf")) {
4091 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004092 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004093 } else {
4094 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004095 err_code |= ERR_ALERT | ERR_FATAL;
4096 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004097 }
4098 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004099 if (curproxy->conf.logformat_string != default_http_log_format &&
4100 curproxy->conf.logformat_string != default_tcp_log_format &&
4101 curproxy->conf.logformat_string != clf_http_log_format)
4102 free(curproxy->conf.logformat_string);
4103 curproxy->conf.logformat_string = logformat;
4104
4105 free(curproxy->conf.lfs_file);
4106 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4107 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004108 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004109 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004110 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004111 if (curproxy->conf.logformat_string != default_http_log_format &&
4112 curproxy->conf.logformat_string != default_tcp_log_format &&
4113 curproxy->conf.logformat_string != clf_http_log_format)
4114 free(curproxy->conf.logformat_string);
4115 curproxy->conf.logformat_string = default_tcp_log_format;
4116
4117 free(curproxy->conf.lfs_file);
4118 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4119 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004120 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 else if (!strcmp(args[1], "tcpka")) {
4122 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004123 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004124 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004125
4126 if (curproxy->cap & PR_CAP_FE)
4127 curproxy->options |= PR_O_TCP_CLI_KA;
4128 if (curproxy->cap & PR_CAP_BE)
4129 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004130 }
4131 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004132 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004133 err_code |= ERR_WARN;
4134
Willy Tarreaubaaee002006-06-26 02:48:02 +02004135 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004136 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004137 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004138 curproxy->options2 &= ~PR_O2_CHK_ANY;
4139 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 if (!*args[2]) { /* no argument */
4141 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4142 curproxy->check_len = strlen(DEF_CHECK_REQ);
4143 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004144 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004145 curproxy->check_req = (char *)malloc(reqlen);
4146 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004147 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004148 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004149 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 if (*args[4])
4151 reqlen += strlen(args[4]);
4152 else
4153 reqlen += strlen("HTTP/1.0");
4154
4155 curproxy->check_req = (char *)malloc(reqlen);
4156 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004157 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004158 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004159 }
4160 else if (!strcmp(args[1], "ssl-hello-chk")) {
4161 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004162 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004163 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004164
Willy Tarreaua534fea2008-08-03 12:19:50 +02004165 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004166 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004167 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004168 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004169 }
Willy Tarreau23677902007-05-08 23:50:35 +02004170 else if (!strcmp(args[1], "smtpchk")) {
4171 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004172 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004173 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004174 curproxy->options2 &= ~PR_O2_CHK_ANY;
4175 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004176
4177 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4178 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4179 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4180 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4181 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4182 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4183 curproxy->check_req = (char *)malloc(reqlen);
4184 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4185 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4186 } else {
4187 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4188 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4189 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4190 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4191 }
4192 }
4193 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004194 else if (!strcmp(args[1], "pgsql-check")) {
4195 /* use PostgreSQL request to check servers' health */
4196 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4197 err_code |= ERR_WARN;
4198
4199 free(curproxy->check_req);
4200 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004201 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004202 curproxy->options2 |= PR_O2_PGSQL_CHK;
4203
4204 if (*(args[2])) {
4205 int cur_arg = 2;
4206
4207 while (*(args[cur_arg])) {
4208 if (strcmp(args[cur_arg], "user") == 0) {
4209 char * packet;
4210 uint32_t packet_len;
4211 uint32_t pv;
4212
4213 /* suboption header - needs additional argument for it */
4214 if (*(args[cur_arg+1]) == 0) {
4215 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4216 file, linenum, args[0], args[1], args[cur_arg]);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
4220
4221 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4222 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4223 pv = htonl(0x30000); /* protocol version 3.0 */
4224
4225 packet = (char*) calloc(1, packet_len);
4226
4227 memcpy(packet + 4, &pv, 4);
4228
4229 /* copy "user" */
4230 memcpy(packet + 8, "user", 4);
4231
4232 /* copy username */
4233 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4234
4235 free(curproxy->check_req);
4236 curproxy->check_req = packet;
4237 curproxy->check_len = packet_len;
4238
4239 packet_len = htonl(packet_len);
4240 memcpy(packet, &packet_len, 4);
4241 cur_arg += 2;
4242 } else {
4243 /* unknown suboption - catchall */
4244 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4245 file, linenum, args[0], args[1]);
4246 err_code |= ERR_ALERT | ERR_FATAL;
4247 goto out;
4248 }
4249 } /* end while loop */
4250 }
4251 }
4252
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004253 else if (!strcmp(args[1], "redis-check")) {
4254 /* use REDIS PING request to check servers' health */
4255 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4256 err_code |= ERR_WARN;
4257
4258 free(curproxy->check_req);
4259 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004260 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004261 curproxy->options2 |= PR_O2_REDIS_CHK;
4262
4263 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4264 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4265 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4266 }
4267
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004268 else if (!strcmp(args[1], "mysql-check")) {
4269 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004270 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4271 err_code |= ERR_WARN;
4272
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004273 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004274 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004275 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004276 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004277
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004278 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004279 * const char mysql40_client_auth_pkt[] = {
4280 * "\x0e\x00\x00" // packet length
4281 * "\x01" // packet number
4282 * "\x00\x00" // client capabilities
4283 * "\x00\x00\x01" // max packet
4284 * "haproxy\x00" // username (null terminated string)
4285 * "\x00" // filler (always 0x00)
4286 * "\x01\x00\x00" // packet length
4287 * "\x00" // packet number
4288 * "\x01" // COM_QUIT command
4289 * };
4290 */
4291
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004292 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4293 * const char mysql41_client_auth_pkt[] = {
4294 * "\x0e\x00\x00\" // packet length
4295 * "\x01" // packet number
4296 * "\x00\x00\x00\x00" // client capabilities
4297 * "\x00\x00\x00\x01" // max packet
4298 * "\x21" // character set (UTF-8)
4299 * char[23] // All zeroes
4300 * "haproxy\x00" // username (null terminated string)
4301 * "\x00" // filler (always 0x00)
4302 * "\x01\x00\x00" // packet length
4303 * "\x00" // packet number
4304 * "\x01" // COM_QUIT command
4305 * };
4306 */
4307
4308
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004309 if (*(args[2])) {
4310 int cur_arg = 2;
4311
4312 while (*(args[cur_arg])) {
4313 if (strcmp(args[cur_arg], "user") == 0) {
4314 char *mysqluser;
4315 int packetlen, reqlen, userlen;
4316
4317 /* suboption header - needs additional argument for it */
4318 if (*(args[cur_arg+1]) == 0) {
4319 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4320 file, linenum, args[0], args[1], args[cur_arg]);
4321 err_code |= ERR_ALERT | ERR_FATAL;
4322 goto out;
4323 }
4324 mysqluser = args[cur_arg + 1];
4325 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004326
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004327 if (*(args[cur_arg+2])) {
4328 if (!strcmp(args[cur_arg+2], "post-41")) {
4329 packetlen = userlen + 7 + 27;
4330 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004331
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004332 free(curproxy->check_req);
4333 curproxy->check_req = (char *)calloc(1, reqlen);
4334 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004335
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004336 snprintf(curproxy->check_req, 4, "%c%c%c",
4337 ((unsigned char) packetlen & 0xff),
4338 ((unsigned char) (packetlen >> 8) & 0xff),
4339 ((unsigned char) (packetlen >> 16) & 0xff));
4340
4341 curproxy->check_req[3] = 1;
4342 curproxy->check_req[5] = 130;
4343 curproxy->check_req[11] = 1;
4344 curproxy->check_req[12] = 33;
4345 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4346 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4347 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4348 cur_arg += 3;
4349 } else {
4350 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4351 err_code |= ERR_ALERT | ERR_FATAL;
4352 goto out;
4353 }
4354 } else {
4355 packetlen = userlen + 7;
4356 reqlen = packetlen + 9;
4357
4358 free(curproxy->check_req);
4359 curproxy->check_req = (char *)calloc(1, reqlen);
4360 curproxy->check_len = reqlen;
4361
4362 snprintf(curproxy->check_req, 4, "%c%c%c",
4363 ((unsigned char) packetlen & 0xff),
4364 ((unsigned char) (packetlen >> 8) & 0xff),
4365 ((unsigned char) (packetlen >> 16) & 0xff));
4366
4367 curproxy->check_req[3] = 1;
4368 curproxy->check_req[5] = 128;
4369 curproxy->check_req[8] = 1;
4370 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4371 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4372 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4373 cur_arg += 2;
4374 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004375 } else {
4376 /* unknown suboption - catchall */
4377 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4378 file, linenum, args[0], args[1]);
4379 err_code |= ERR_ALERT | ERR_FATAL;
4380 goto out;
4381 }
4382 } /* end while loop */
4383 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004384 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004385 else if (!strcmp(args[1], "ldap-check")) {
4386 /* use LDAP request to check servers' health */
4387 free(curproxy->check_req);
4388 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004389 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004390 curproxy->options2 |= PR_O2_LDAP_CHK;
4391
4392 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4393 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4394 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4395 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004396 else if (!strcmp(args[1], "tcp-check")) {
4397 /* use raw TCPCHK send/expect to check servers' health */
4398 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4399 err_code |= ERR_WARN;
4400
4401 free(curproxy->check_req);
4402 curproxy->check_req = NULL;
4403 curproxy->options2 &= ~PR_O2_CHK_ANY;
4404 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4405 }
Simon Horman98637e52014-06-20 12:30:16 +09004406 else if (!strcmp(args[1], "external-check")) {
4407 /* excute an external command to check servers' health */
4408 free(curproxy->check_req);
4409 curproxy->check_req = NULL;
4410 curproxy->options2 &= ~PR_O2_CHK_ANY;
4411 curproxy->options2 |= PR_O2_EXT_CHK;
4412 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004413 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004414 int cur_arg;
4415
4416 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4417 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004418 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004419
Willy Tarreau87cf5142011-08-19 22:57:24 +02004420 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004421
4422 free(curproxy->fwdfor_hdr_name);
4423 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4424 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4425
4426 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4427 cur_arg = 2;
4428 while (*(args[cur_arg])) {
4429 if (!strcmp(args[cur_arg], "except")) {
4430 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004431 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004432 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4433 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004434 err_code |= ERR_ALERT | ERR_FATAL;
4435 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004436 }
4437 /* flush useless bits */
4438 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004439 cur_arg += 2;
4440 } else if (!strcmp(args[cur_arg], "header")) {
4441 /* suboption header - needs additional argument for it */
4442 if (*(args[cur_arg+1]) == 0) {
4443 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4444 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004445 err_code |= ERR_ALERT | ERR_FATAL;
4446 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004447 }
4448 free(curproxy->fwdfor_hdr_name);
4449 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4450 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4451 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004452 } else if (!strcmp(args[cur_arg], "if-none")) {
4453 curproxy->options &= ~PR_O_FF_ALWAYS;
4454 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004455 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004456 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004457 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004458 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004459 err_code |= ERR_ALERT | ERR_FATAL;
4460 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004461 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004462 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004463 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004464 else if (!strcmp(args[1], "originalto")) {
4465 int cur_arg;
4466
4467 /* insert x-original-to field, but not for the IP address listed as an except.
4468 * set default options (ie: bitfield, header name, etc)
4469 */
4470
4471 curproxy->options |= PR_O_ORGTO;
4472
4473 free(curproxy->orgto_hdr_name);
4474 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4475 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4476
Willy Tarreau87cf5142011-08-19 22:57:24 +02004477 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004478 cur_arg = 2;
4479 while (*(args[cur_arg])) {
4480 if (!strcmp(args[cur_arg], "except")) {
4481 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004482 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 +02004483 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4484 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004485 err_code |= ERR_ALERT | ERR_FATAL;
4486 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004487 }
4488 /* flush useless bits */
4489 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4490 cur_arg += 2;
4491 } else if (!strcmp(args[cur_arg], "header")) {
4492 /* suboption header - needs additional argument for it */
4493 if (*(args[cur_arg+1]) == 0) {
4494 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4495 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004496 err_code |= ERR_ALERT | ERR_FATAL;
4497 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004498 }
4499 free(curproxy->orgto_hdr_name);
4500 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4501 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4502 cur_arg += 2;
4503 } else {
4504 /* unknown suboption - catchall */
4505 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4506 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004509 }
4510 } /* end while loop */
4511 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004512 else {
4513 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004514 err_code |= ERR_ALERT | ERR_FATAL;
4515 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004516 }
Willy Tarreau93893792009-07-23 13:19:11 +02004517 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004518 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004519 else if (!strcmp(args[0], "default_backend")) {
4520 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004521 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004522
4523 if (*(args[1]) == 0) {
4524 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_ALERT | ERR_FATAL;
4526 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004527 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004528 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004529 curproxy->defbe.name = strdup(args[1]);
4530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004532 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004533 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004534
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004535 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4536 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 +01004537 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004538 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004539 /* enable reconnections to dispatch */
4540 curproxy->options |= PR_O_REDISP;
4541 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004542 else if (!strcmp(args[0], "http-check")) {
4543 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004544 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004545
4546 if (strcmp(args[1], "disable-on-404") == 0) {
4547 /* enable a graceful server shutdown on an HTTP 404 response */
4548 curproxy->options |= PR_O_DISABLE404;
4549 }
Willy Tarreauef781042010-01-27 11:53:01 +01004550 else if (strcmp(args[1], "send-state") == 0) {
4551 /* enable emission of the apparent state of a server in HTTP checks */
4552 curproxy->options2 |= PR_O2_CHK_SNDST;
4553 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004554 else if (strcmp(args[1], "expect") == 0) {
4555 const char *ptr_arg;
4556 int cur_arg;
4557
4558 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4559 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4560 err_code |= ERR_ALERT | ERR_FATAL;
4561 goto out;
4562 }
4563
4564 cur_arg = 2;
4565 /* consider exclamation marks, sole or at the beginning of a word */
4566 while (*(ptr_arg = args[cur_arg])) {
4567 while (*ptr_arg == '!') {
4568 curproxy->options2 ^= PR_O2_EXP_INV;
4569 ptr_arg++;
4570 }
4571 if (*ptr_arg)
4572 break;
4573 cur_arg++;
4574 }
4575 /* now ptr_arg points to the beginning of a word past any possible
4576 * exclamation mark, and cur_arg is the argument which holds this word.
4577 */
4578 if (strcmp(ptr_arg, "status") == 0) {
4579 if (!*(args[cur_arg + 1])) {
4580 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4581 file, linenum, args[0], args[1], ptr_arg);
4582 err_code |= ERR_ALERT | ERR_FATAL;
4583 goto out;
4584 }
4585 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004586 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004587 curproxy->expect_str = strdup(args[cur_arg + 1]);
4588 }
4589 else if (strcmp(ptr_arg, "string") == 0) {
4590 if (!*(args[cur_arg + 1])) {
4591 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4592 file, linenum, args[0], args[1], ptr_arg);
4593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
4595 }
4596 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004597 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004598 curproxy->expect_str = strdup(args[cur_arg + 1]);
4599 }
4600 else if (strcmp(ptr_arg, "rstatus") == 0) {
4601 if (!*(args[cur_arg + 1])) {
4602 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4603 file, linenum, args[0], args[1], ptr_arg);
4604 err_code |= ERR_ALERT | ERR_FATAL;
4605 goto out;
4606 }
4607 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004608 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004609 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004610 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004611 free(curproxy->expect_regex);
4612 curproxy->expect_regex = NULL;
4613 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004614 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004615 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4616 error = NULL;
4617 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4618 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4619 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4620 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
4623 }
4624 }
4625 else if (strcmp(ptr_arg, "rstring") == 0) {
4626 if (!*(args[cur_arg + 1])) {
4627 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4628 file, linenum, args[0], args[1], ptr_arg);
4629 err_code |= ERR_ALERT | ERR_FATAL;
4630 goto out;
4631 }
4632 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004633 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004634 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004635 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004636 free(curproxy->expect_regex);
4637 curproxy->expect_regex = NULL;
4638 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004639 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004640 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4641 error = NULL;
4642 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4643 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4644 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4645 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
4649 }
4650 else {
4651 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4652 file, linenum, args[0], args[1], ptr_arg);
4653 err_code |= ERR_ALERT | ERR_FATAL;
4654 goto out;
4655 }
4656 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004657 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004658 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 +02004659 err_code |= ERR_ALERT | ERR_FATAL;
4660 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004661 }
4662 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004663 else if (!strcmp(args[0], "tcp-check")) {
4664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4665 err_code |= ERR_WARN;
4666
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004667 if (strcmp(args[1], "connect") == 0) {
4668 const char *ptr_arg;
4669 int cur_arg;
4670 struct tcpcheck_rule *tcpcheck;
4671 struct list *l;
4672
4673 /* check if first rule is also a 'connect' action */
4674 l = (struct list *)&curproxy->tcpcheck_rules;
4675 if (l->p != l->n) {
4676 tcpcheck = (struct tcpcheck_rule *)l->n;
4677 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4678 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4679 file, linenum);
4680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
4683 }
4684
4685 cur_arg = 2;
4686 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4687 tcpcheck->action = TCPCHK_ACT_CONNECT;
4688
4689 /* parsing each parameters to fill up the rule */
4690 while (*(ptr_arg = args[cur_arg])) {
4691 /* tcp port */
4692 if (strcmp(args[cur_arg], "port") == 0) {
4693 if ( (atol(args[cur_arg + 1]) > 65535) ||
4694 (atol(args[cur_arg + 1]) < 1) ){
4695 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4696 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4697 err_code |= ERR_ALERT | ERR_FATAL;
4698 goto out;
4699 }
4700 tcpcheck->port = atol(args[cur_arg + 1]);
4701 cur_arg += 2;
4702 }
4703 /* send proxy protocol */
4704 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4705 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4706 cur_arg++;
4707 }
4708#ifdef USE_OPENSSL
4709 else if (strcmp(args[cur_arg], "ssl") == 0) {
4710 curproxy->options |= PR_O_TCPCHK_SSL;
4711 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4712 cur_arg++;
4713 }
4714#endif /* USE_OPENSSL */
4715 else {
4716#ifdef USE_OPENSSL
4717 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4718#else /* USE_OPENSSL */
4719 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4720#endif /* USE_OPENSSL */
4721 file, linenum, args[0], args[1], args[cur_arg]);
4722 err_code |= ERR_ALERT | ERR_FATAL;
4723 goto out;
4724 }
4725
4726 }
4727
4728 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4729 }
4730 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004731 if (! *(args[2]) ) {
4732 /* SEND string expected */
4733 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4734 file, linenum, args[0], args[1], args[2]);
4735 err_code |= ERR_ALERT | ERR_FATAL;
4736 goto out;
4737 } else {
4738 struct tcpcheck_rule *tcpcheck;
4739
4740 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4741
4742 tcpcheck->action = TCPCHK_ACT_SEND;
4743 tcpcheck->string_len = strlen(args[2]);
4744 tcpcheck->string = strdup(args[2]);
4745 tcpcheck->expect_regex = NULL;
4746
4747 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4748 }
4749 }
4750 else if (strcmp(args[1], "send-binary") == 0) {
4751 if (! *(args[2]) ) {
4752 /* SEND binary string expected */
4753 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4754 file, linenum, args[0], args[1], args[2]);
4755 err_code |= ERR_ALERT | ERR_FATAL;
4756 goto out;
4757 } else {
4758 struct tcpcheck_rule *tcpcheck;
4759 char *err = NULL;
4760
4761 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4762
4763 tcpcheck->action = TCPCHK_ACT_SEND;
4764 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4765 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4766 file, linenum, args[0], args[1], args[2], err);
4767 err_code |= ERR_ALERT | ERR_FATAL;
4768 goto out;
4769 }
4770 tcpcheck->expect_regex = NULL;
4771
4772 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4773 }
4774 }
4775 else if (strcmp(args[1], "expect") == 0) {
4776 const char *ptr_arg;
4777 int cur_arg;
4778 int inverse = 0;
4779
4780 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4781 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4782 err_code |= ERR_ALERT | ERR_FATAL;
4783 goto out;
4784 }
4785
4786 cur_arg = 2;
4787 /* consider exclamation marks, sole or at the beginning of a word */
4788 while (*(ptr_arg = args[cur_arg])) {
4789 while (*ptr_arg == '!') {
4790 inverse = !inverse;
4791 ptr_arg++;
4792 }
4793 if (*ptr_arg)
4794 break;
4795 cur_arg++;
4796 }
4797 /* now ptr_arg points to the beginning of a word past any possible
4798 * exclamation mark, and cur_arg is the argument which holds this word.
4799 */
4800 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004801 struct tcpcheck_rule *tcpcheck;
4802 char *err = NULL;
4803
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004804 if (!*(args[cur_arg + 1])) {
4805 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4806 file, linenum, args[0], args[1], ptr_arg);
4807 err_code |= ERR_ALERT | ERR_FATAL;
4808 goto out;
4809 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004810
4811 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4812
4813 tcpcheck->action = TCPCHK_ACT_EXPECT;
4814 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4815 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4816 file, linenum, args[0], args[1], args[2], err);
4817 err_code |= ERR_ALERT | ERR_FATAL;
4818 goto out;
4819 }
4820 tcpcheck->expect_regex = NULL;
4821 tcpcheck->inverse = inverse;
4822
4823 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4824 }
4825 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004826 struct tcpcheck_rule *tcpcheck;
4827
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004828 if (!*(args[cur_arg + 1])) {
4829 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4830 file, linenum, args[0], args[1], ptr_arg);
4831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
4833 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004834
4835 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4836
4837 tcpcheck->action = TCPCHK_ACT_EXPECT;
4838 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4839 tcpcheck->string = strdup(args[cur_arg + 1]);
4840 tcpcheck->expect_regex = NULL;
4841 tcpcheck->inverse = inverse;
4842
4843 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4844 }
4845 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004846 struct tcpcheck_rule *tcpcheck;
4847
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004848 if (!*(args[cur_arg + 1])) {
4849 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4850 file, linenum, args[0], args[1], ptr_arg);
4851 err_code |= ERR_ALERT | ERR_FATAL;
4852 goto out;
4853 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004854
4855 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4856
4857 tcpcheck->action = TCPCHK_ACT_EXPECT;
4858 tcpcheck->string_len = 0;
4859 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004860 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4861 error = NULL;
4862 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4863 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4864 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4865 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
4869 tcpcheck->inverse = inverse;
4870
4871 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4872 }
4873 else {
4874 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4875 file, linenum, args[0], args[1], ptr_arg);
4876 err_code |= ERR_ALERT | ERR_FATAL;
4877 goto out;
4878 }
4879 }
4880 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004881 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
4884 }
4885 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004886 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004887 if (curproxy == &defproxy) {
4888 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004889 err_code |= ERR_ALERT | ERR_FATAL;
4890 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004891 }
4892
Willy Tarreaub80c2302007-11-30 20:51:32 +01004893 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004894 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004895
4896 if (strcmp(args[1], "fail") == 0) {
4897 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004898 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004899 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4900 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004903 }
4904
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004905 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4906 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4907 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004910 }
4911 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4912 }
4913 else {
4914 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004915 err_code |= ERR_ALERT | ERR_FATAL;
4916 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004917 }
4918 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004919#ifdef TPROXY
4920 else if (!strcmp(args[0], "transparent")) {
4921 /* enable transparent proxy connections */
4922 curproxy->options |= PR_O_TRANSP;
4923 }
4924#endif
4925 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004926 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004928
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 if (*(args[1]) == 0) {
4930 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_ALERT | ERR_FATAL;
4932 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004933 }
4934 curproxy->maxconn = atol(args[1]);
4935 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004936 else if (!strcmp(args[0], "backlog")) { /* backlog */
4937 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004939
4940 if (*(args[1]) == 0) {
4941 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004942 err_code |= ERR_ALERT | ERR_FATAL;
4943 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004944 }
4945 curproxy->backlog = atol(args[1]);
4946 }
Willy Tarreau86034312006-12-29 00:10:33 +01004947 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004948 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004950
Willy Tarreau86034312006-12-29 00:10:33 +01004951 if (*(args[1]) == 0) {
4952 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004955 }
4956 curproxy->fullconn = atol(args[1]);
4957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004958 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4959 if (*(args[1]) == 0) {
4960 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004963 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004964 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4965 if (err) {
4966 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4967 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004968 err_code |= ERR_ALERT | ERR_FATAL;
4969 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004970 }
4971 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004972 }
4973 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004974 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004975 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004976 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004977
Willy Tarreaubaaee002006-06-26 02:48:02 +02004978 if (curproxy == &defproxy) {
4979 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004982 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004983 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004984 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004985
Willy Tarreau902636f2013-03-10 19:44:48 +01004986 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004987 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004988 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004989 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004990 goto out;
4991 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004992
4993 proto = protocol_by_family(sk->ss_family);
4994 if (!proto || !proto->connect) {
4995 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4996 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
4999 }
5000
5001 if (port1 != port2) {
5002 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5003 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005006 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005007
5008 if (!port1) {
5009 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5010 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005011 err_code |= ERR_ALERT | ERR_FATAL;
5012 goto out;
5013 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005014
Willy Tarreaud5191e72010-02-09 20:50:45 +01005015 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005016 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005017 }
5018 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005019 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005021
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005022 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5023 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005024 err_code |= ERR_ALERT | ERR_FATAL;
5025 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005026 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005027 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005028 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005029 /**
5030 * The syntax for hash-type config element is
5031 * hash-type {map-based|consistent} [[<algo>] avalanche]
5032 *
5033 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5034 */
5035 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005036
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005037 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5038 err_code |= ERR_WARN;
5039
5040 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005041 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5042 }
5043 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005044 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5045 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005046 else if (strcmp(args[1], "avalanche") == 0) {
5047 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]);
5048 err_code |= ERR_ALERT | ERR_FATAL;
5049 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005050 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005051 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005052 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
5055 }
Bhaskar98634f02013-10-29 23:30:51 -04005056
5057 /* set the hash function to use */
5058 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005059 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005060 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005061
5062 /* if consistent with no argument, then avalanche modifier is also applied */
5063 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5064 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005065 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005066 /* set the hash function */
5067 if (!strcmp(args[2], "sdbm")) {
5068 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5069 }
5070 else if (!strcmp(args[2], "djb2")) {
5071 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005072 }
5073 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005074 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005075 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005076 else if (!strcmp(args[2], "crc32")) {
5077 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5078 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005079 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005080 Alert("parsing [%s:%d] : '%s' only supports 'sdbm', 'djb2', 'crc32', or 'wt6' hash functions.\n", file, linenum, args[0]);
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
5083 }
5084
5085 /* set the hash modifier */
5086 if (!strcmp(args[3], "avalanche")) {
5087 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5088 }
5089 else if (*args[3]) {
5090 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005094 }
William Lallemanda73203e2012-03-12 12:48:57 +01005095 }
William Lallemanda73203e2012-03-12 12:48:57 +01005096 else if (strcmp(args[0], "unique-id-format") == 0) {
5097 if (!*(args[1])) {
5098 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5099 err_code |= ERR_ALERT | ERR_FATAL;
5100 goto out;
5101 }
William Lallemand3203ff42012-11-11 17:30:56 +01005102 if (*(args[2])) {
5103 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5104 err_code |= ERR_ALERT | ERR_FATAL;
5105 goto out;
5106 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005107 free(curproxy->conf.uniqueid_format_string);
5108 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005109
Willy Tarreau62a61232013-04-12 18:13:46 +02005110 free(curproxy->conf.uif_file);
5111 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5112 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005113 }
William Lallemanda73203e2012-03-12 12:48:57 +01005114
5115 else if (strcmp(args[0], "unique-id-header") == 0) {
5116 if (!*(args[1])) {
5117 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5118 err_code |= ERR_ALERT | ERR_FATAL;
5119 goto out;
5120 }
5121 free(curproxy->header_unique_id);
5122 curproxy->header_unique_id = strdup(args[1]);
5123 }
5124
William Lallemand723b73a2012-02-08 16:37:49 +01005125 else if (strcmp(args[0], "log-format") == 0) {
5126 if (!*(args[1])) {
5127 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5128 err_code |= ERR_ALERT | ERR_FATAL;
5129 goto out;
5130 }
William Lallemand3203ff42012-11-11 17:30:56 +01005131 if (*(args[2])) {
5132 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5133 err_code |= ERR_ALERT | ERR_FATAL;
5134 goto out;
5135 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005136
Willy Tarreau62a61232013-04-12 18:13:46 +02005137 if (curproxy->conf.logformat_string != default_http_log_format &&
5138 curproxy->conf.logformat_string != default_tcp_log_format &&
5139 curproxy->conf.logformat_string != clf_http_log_format)
5140 free(curproxy->conf.logformat_string);
5141 curproxy->conf.logformat_string = strdup(args[1]);
5142
5143 free(curproxy->conf.lfs_file);
5144 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5145 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005146
5147 /* get a chance to improve log-format error reporting by
5148 * reporting the correct line-number when possible.
5149 */
5150 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5151 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5152 file, linenum, curproxy->id);
5153 err_code |= ERR_WARN;
5154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005155 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005156 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5157 if (*(args[1]) == 0) {
5158 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5159 err_code |= ERR_ALERT | ERR_FATAL;
5160 goto out;
5161 }
5162 free(curproxy->log_tag);
5163 curproxy->log_tag = strdup(args[1]);
5164 }
William Lallemand0f99e342011-10-12 17:50:54 +02005165 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5166 /* delete previous herited or defined syslog servers */
5167 struct logsrv *back;
5168
5169 if (*(args[1]) != 0) {
5170 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5171 err_code |= ERR_ALERT | ERR_FATAL;
5172 goto out;
5173 }
5174
William Lallemand723b73a2012-02-08 16:37:49 +01005175 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5176 LIST_DEL(&tmplogsrv->list);
5177 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005178 }
5179 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005181 struct logsrv *logsrv;
5182
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005184 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005185 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005186 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005187 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005188 LIST_INIT(&node->list);
5189 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191 }
5192 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005193 struct sockaddr_storage *sk;
5194 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005195 int arg = 0;
5196 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005197
5198 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005199
Willy Tarreau18324f52014-06-27 18:10:07 +02005200 /* just after the address, a length may be specified */
5201 if (strcmp(args[arg+2], "len") == 0) {
5202 len = atoi(args[arg+3]);
5203 if (len < 80 || len > 65535) {
5204 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5205 file, linenum, args[arg+3]);
5206 err_code |= ERR_ALERT | ERR_FATAL;
5207 goto out;
5208 }
5209 logsrv->maxlen = len;
5210
5211 /* skip these two args */
5212 arg += 2;
5213 }
5214 else
5215 logsrv->maxlen = MAX_SYSLOG_LEN;
5216
5217 if (logsrv->maxlen > global.max_syslog_len) {
5218 global.max_syslog_len = logsrv->maxlen;
5219 logline = realloc(logline, global.max_syslog_len + 1);
5220 }
5221
5222 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005223 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005224 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005225 err_code |= ERR_ALERT | ERR_FATAL;
5226 goto out;
5227
Willy Tarreaubaaee002006-06-26 02:48:02 +02005228 }
5229
William Lallemand0f99e342011-10-12 17:50:54 +02005230 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005231 if (*(args[arg+3])) {
5232 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005233 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005234 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
5237
Willy Tarreaubaaee002006-06-26 02:48:02 +02005238 }
5239 }
5240
William Lallemand0f99e342011-10-12 17:50:54 +02005241 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005242 if (*(args[arg+4])) {
5243 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005244 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005245 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005249 }
5250 }
5251
Willy Tarreau902636f2013-03-10 19:44:48 +01005252 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005253 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005254 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005255 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005256 goto out;
5257 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005258
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005259 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005260
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005261 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005262 if (port1 != port2) {
5263 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5264 file, linenum, args[0], args[1]);
5265 err_code |= ERR_ALERT | ERR_FATAL;
5266 goto out;
5267 }
5268
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005269 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005270 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 }
William Lallemand0f99e342011-10-12 17:50:54 +02005272
5273 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005274 }
5275 else {
5276 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5277 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005278 err_code |= ERR_ALERT | ERR_FATAL;
5279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005280 }
5281 }
5282 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005283 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005284 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005285 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005286 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005287
Willy Tarreau977b8e42006-12-29 14:19:17 +01005288 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005289 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005290
Willy Tarreaubaaee002006-06-26 02:48:02 +02005291 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005292 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5293 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005294 err_code |= ERR_ALERT | ERR_FATAL;
5295 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005296 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005297
5298 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005299 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5300 free(curproxy->conn_src.iface_name);
5301 curproxy->conn_src.iface_name = NULL;
5302 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005303
Willy Tarreau902636f2013-03-10 19:44:48 +01005304 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005305 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005306 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005307 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005308 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005309 goto out;
5310 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005311
5312 proto = protocol_by_family(sk->ss_family);
5313 if (!proto || !proto->connect) {
5314 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005315 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005319
5320 if (port1 != port2) {
5321 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5322 file, linenum, args[0], args[1]);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
5326
Willy Tarreauef9a3602012-12-08 22:29:20 +01005327 curproxy->conn_src.source_addr = *sk;
5328 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005329
5330 cur_arg = 2;
5331 while (*(args[cur_arg])) {
5332 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005333#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5334#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005335 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005336 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5337 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005340 }
5341#endif
5342 if (!*args[cur_arg + 1]) {
5343 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5344 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005347 }
5348
5349 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005350 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5351 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005352 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005353 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5354 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005355 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5356 char *name, *end;
5357
5358 name = args[cur_arg+1] + 7;
5359 while (isspace(*name))
5360 name++;
5361
5362 end = name;
5363 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5364 end++;
5365
Willy Tarreauef9a3602012-12-08 22:29:20 +01005366 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5367 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5368 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5369 curproxy->conn_src.bind_hdr_len = end - name;
5370 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5371 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5372 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005373
5374 /* now look for an occurrence number */
5375 while (isspace(*end))
5376 end++;
5377 if (*end == ',') {
5378 end++;
5379 name = end;
5380 if (*end == '-')
5381 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005382 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005383 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005384 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005385 }
5386
Willy Tarreauef9a3602012-12-08 22:29:20 +01005387 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005388 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5389 " occurrences values smaller than %d.\n",
5390 file, linenum, MAX_HDR_HISTORY);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
5393 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005394 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005395 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005396
Willy Tarreau902636f2013-03-10 19:44:48 +01005397 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005398 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005399 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005400 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005401 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005402 goto out;
5403 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005404
5405 proto = protocol_by_family(sk->ss_family);
5406 if (!proto || !proto->connect) {
5407 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5408 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005412
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005413 if (port1 != port2) {
5414 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5415 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
5418 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005419 curproxy->conn_src.tproxy_addr = *sk;
5420 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005421 }
5422 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005423#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005424 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005425#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005426#else /* no TPROXY support */
5427 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005428 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005429 err_code |= ERR_ALERT | ERR_FATAL;
5430 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005431#endif
5432 cur_arg += 2;
5433 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005434 }
5435
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005436 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5437#ifdef SO_BINDTODEVICE
5438 if (!*args[cur_arg + 1]) {
5439 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5440 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005443 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005444 free(curproxy->conn_src.iface_name);
5445 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5446 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005447 global.last_checks |= LSTCHK_NETADM;
5448#else
5449 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5450 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005453#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005454 cur_arg += 2;
5455 continue;
5456 }
5457 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005458 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005463 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5464 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5465 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005468 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005469 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005470 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5472 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005473 err_code |= ERR_ALERT | ERR_FATAL;
5474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005476
5477 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005478 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005479 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005480 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 }
5483 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005484 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005485 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005486 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005487 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 }
5490 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005491 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005492 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005493 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005494 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 }
5497 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005498 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005499 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005500 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005501 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 }
5504 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005505 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005506 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005507 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005508 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005510 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005511 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005513 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005514 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005516 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005517 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005518 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005519 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005520 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005521 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005522 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005523 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005524
5525 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5526 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 +01005527 }
5528 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005529 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005530 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005531 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005532 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005533 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005534
5535 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5536 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 +01005537 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005538 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005539 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5541 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005542 err_code |= ERR_ALERT | ERR_FATAL;
5543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005545
5546 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005547 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005548 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005549 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551 }
5552 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005553 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005554 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005555 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005556 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 }
5559 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005560 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005561 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005562 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005563 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 }
5566 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005567 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005568 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005569 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005570 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 }
5573 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005574 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005575 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005576 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005577 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005580 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005581 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005582 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005583 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005584 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005585 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005586 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005588 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005589
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 if (curproxy == &defproxy) {
5591 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005595 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005596 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005597
Willy Tarreaubaaee002006-06-26 02:48:02 +02005598 if (*(args[1]) == 0) {
5599 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005602 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005603
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005604 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005605 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5606 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5607 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
5610 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005611 err_code |= warnif_cond_conflicts(cond,
5612 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5613 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005614 }
5615 else if (*args[2]) {
5616 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5617 file, linenum, args[0], args[2]);
5618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
5621
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005622 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005623 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005624 wl->s = strdup(args[1]);
5625 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005626 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 }
5628 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005629 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5631 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005635
Willy Tarreauade5ec42010-01-28 19:33:49 +01005636 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005637 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005638 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005639 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
5642 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005643 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005644 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005645 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005646 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 }
5649 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005650 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005651 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005652 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005653 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
5656 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005657 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5659 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 }
5663
Willy Tarreauade5ec42010-01-28 19:33:49 +01005664 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005665 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005666 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005667 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005671 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005672 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005673 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005674 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
5677 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005678 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005679 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005680 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005681 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
5684 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005685 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005686
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 if (curproxy == &defproxy) {
5688 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005692 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005693 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005694
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 if (*(args[1]) == 0) {
5696 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005697 err_code |= ERR_ALERT | ERR_FATAL;
5698 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005699 }
5700
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005701 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005702 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5703 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5704 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005705 err_code |= ERR_ALERT | ERR_FATAL;
5706 goto out;
5707 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005708 err_code |= warnif_cond_conflicts(cond,
5709 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5710 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005711 }
5712 else if (*args[2]) {
5713 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5714 file, linenum, args[0], args[2]);
5715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
5717 }
5718
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005719 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005720 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005721 wl->s = strdup(args[1]);
5722 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005723 }
5724 else if (!strcmp(args[0], "errorloc") ||
5725 !strcmp(args[0], "errorloc302") ||
5726 !strcmp(args[0], "errorloc303")) { /* error location */
5727 int errnum, errlen;
5728 char *err;
5729
Willy Tarreau977b8e42006-12-29 14:19:17 +01005730 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005731 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005732
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005734 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005737 }
5738
5739 errnum = atol(args[1]);
5740 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005741 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5742 err = malloc(errlen);
5743 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005745 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5746 err = malloc(errlen);
5747 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
5749
Willy Tarreau0f772532006-12-23 20:51:41 +01005750 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5751 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005752 chunk_destroy(&curproxy->errmsg[rc]);
5753 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005754 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005757
5758 if (rc >= HTTP_ERR_SIZE) {
5759 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5760 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005761 free(err);
5762 }
5763 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005764 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5765 int errnum, errlen, fd;
5766 char *err;
5767 struct stat stat;
5768
5769 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005770 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005771
5772 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005773 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005774 err_code |= ERR_ALERT | ERR_FATAL;
5775 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005776 }
5777
5778 fd = open(args[2], O_RDONLY);
5779 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5780 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5781 file, linenum, args[2], args[1]);
5782 if (fd >= 0)
5783 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005784 err_code |= ERR_ALERT | ERR_FATAL;
5785 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005786 }
5787
Willy Tarreau27a674e2009-08-17 07:23:33 +02005788 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005789 errlen = stat.st_size;
5790 } else {
5791 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005792 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005793 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005794 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005795 }
5796
5797 err = malloc(errlen); /* malloc() must succeed during parsing */
5798 errnum = read(fd, err, errlen);
5799 if (errnum != errlen) {
5800 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5801 file, linenum, args[2], args[1]);
5802 close(fd);
5803 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005804 err_code |= ERR_ALERT | ERR_FATAL;
5805 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005806 }
5807 close(fd);
5808
5809 errnum = atol(args[1]);
5810 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5811 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005812 chunk_destroy(&curproxy->errmsg[rc]);
5813 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005814 break;
5815 }
5816 }
5817
5818 if (rc >= HTTP_ERR_SIZE) {
5819 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5820 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005821 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005822 free(err);
5823 }
5824 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005825 else if (!strcmp(args[0], "compression")) {
5826 struct comp *comp;
5827 if (curproxy->comp == NULL) {
5828 comp = calloc(1, sizeof(struct comp));
5829 curproxy->comp = comp;
5830 } else {
5831 comp = curproxy->comp;
5832 }
5833
5834 if (!strcmp(args[1], "algo")) {
5835 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005836 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005837
William Lallemand82fe75c2012-10-23 10:25:10 +02005838 cur_arg = 2;
5839 if (!*args[cur_arg]) {
5840 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5841 file, linenum, args[0]);
5842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
5844 }
5845 while (*(args[cur_arg])) {
5846 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5847 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5848 file, linenum, args[0], args[cur_arg]);
5849 err_code |= ERR_ALERT | ERR_FATAL;
5850 goto out;
5851 }
William Lallemand552df672012-11-07 13:21:47 +01005852 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5853 curproxy->comp->algos->end(&ctx);
5854 } else {
5855 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5856 file, linenum, args[0], args[cur_arg]);
5857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
5859 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005860 cur_arg ++;
5861 continue;
5862 }
5863 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005864 else if (!strcmp(args[1], "offload")) {
5865 comp->offload = 1;
5866 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005867 else if (!strcmp(args[1], "type")) {
5868 int cur_arg;
5869 cur_arg = 2;
5870 if (!*args[cur_arg]) {
5871 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5872 file, linenum, args[0]);
5873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
5875 }
5876 while (*(args[cur_arg])) {
5877 comp_append_type(comp, args[cur_arg]);
5878 cur_arg ++;
5879 continue;
5880 }
5881 }
5882 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005883 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005884 file, linenum, args[0]);
5885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
5887 }
5888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005889 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005890 struct cfg_kw_list *kwl;
5891 int index;
5892
5893 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5894 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5895 if (kwl->kw[index].section != CFG_LISTEN)
5896 continue;
5897 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5898 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005899 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005900 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005901 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005902 err_code |= ERR_ALERT | ERR_FATAL;
5903 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005904 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005905 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005906 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005907 err_code |= ERR_WARN;
5908 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005909 }
Willy Tarreau93893792009-07-23 13:19:11 +02005910 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005911 }
5912 }
5913 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005914
Willy Tarreau6daf3432008-01-22 16:44:08 +01005915 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005916 err_code |= ERR_ALERT | ERR_FATAL;
5917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005918 }
Willy Tarreau93893792009-07-23 13:19:11 +02005919 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005920 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005921 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922}
5923
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005924int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005925cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5926{
5927#ifdef CONFIG_HAP_NS
5928 const char *err;
5929 const char *item = args[0];
5930
5931 if (!strcmp(item, "namespace_list")) {
5932 return 0;
5933 }
5934 else if (!strcmp(item, "namespace")) {
5935 size_t idx = 1;
5936 const char *current;
5937 while (*(current = args[idx++])) {
5938 err = invalid_char(current);
5939 if (err) {
5940 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5941 file, linenum, *err, item, current);
5942 return ERR_ALERT | ERR_FATAL;
5943 }
5944
5945 if (netns_store_lookup(current, strlen(current))) {
5946 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5947 file, linenum, current);
5948 return ERR_ALERT | ERR_FATAL;
5949 }
5950 if (!netns_store_insert(current)) {
5951 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5952 file, linenum, current);
5953 return ERR_ALERT | ERR_FATAL;
5954 }
5955 }
5956 }
5957
5958 return 0;
5959#else
5960 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5961 file, linenum);
5962 return ERR_ALERT | ERR_FATAL;
5963#endif
5964}
5965
5966int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005967cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5968{
5969
5970 int err_code = 0;
5971 const char *err;
5972
5973 if (!strcmp(args[0], "userlist")) { /* new userlist */
5974 struct userlist *newul;
5975
5976 if (!*args[1]) {
5977 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5978 file, linenum, args[0]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
5982
5983 err = invalid_char(args[1]);
5984 if (err) {
5985 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5986 file, linenum, *err, args[0], args[1]);
5987 err_code |= ERR_ALERT | ERR_FATAL;
5988 goto out;
5989 }
5990
5991 for (newul = userlist; newul; newul = newul->next)
5992 if (!strcmp(newul->name, args[1])) {
5993 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5994 file, linenum, args[1]);
5995 err_code |= ERR_WARN;
5996 goto out;
5997 }
5998
5999 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6000 if (!newul) {
6001 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6002 err_code |= ERR_ALERT | ERR_ABORT;
6003 goto out;
6004 }
6005
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006006 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006007 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006008 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6009 err_code |= ERR_ALERT | ERR_ABORT;
6010 goto out;
6011 }
6012
6013 newul->next = userlist;
6014 userlist = newul;
6015
6016 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006017 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006018 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006019 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006020
6021 if (!*args[1]) {
6022 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6023 file, linenum, args[0]);
6024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
6026 }
6027
6028 err = invalid_char(args[1]);
6029 if (err) {
6030 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6031 file, linenum, *err, args[0], args[1]);
6032 err_code |= ERR_ALERT | ERR_FATAL;
6033 goto out;
6034 }
6035
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006036 for (ag = userlist->groups; ag; ag = ag->next)
6037 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006038 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6039 file, linenum, args[1], userlist->name);
6040 err_code |= ERR_ALERT;
6041 goto out;
6042 }
6043
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006044 ag = calloc(1, sizeof(*ag));
6045 if (!ag) {
6046 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6047 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006048 goto out;
6049 }
6050
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006051 ag->name = strdup(args[1]);
6052 if (!ag) {
6053 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6054 err_code |= ERR_ALERT | ERR_ABORT;
6055 goto out;
6056 }
6057
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006058 cur_arg = 2;
6059
6060 while (*args[cur_arg]) {
6061 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006062 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006063 cur_arg += 2;
6064 continue;
6065 } else {
6066 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6067 file, linenum, args[0]);
6068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
6070 }
6071 }
6072
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006073 ag->next = userlist->groups;
6074 userlist->groups = ag;
6075
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006076 } else if (!strcmp(args[0], "user")) { /* new user */
6077 struct auth_users *newuser;
6078 int cur_arg;
6079
6080 if (!*args[1]) {
6081 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6082 file, linenum, args[0]);
6083 err_code |= ERR_ALERT | ERR_FATAL;
6084 goto out;
6085 }
6086
6087 for (newuser = userlist->users; newuser; newuser = newuser->next)
6088 if (!strcmp(newuser->user, args[1])) {
6089 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6090 file, linenum, args[1], userlist->name);
6091 err_code |= ERR_ALERT;
6092 goto out;
6093 }
6094
6095 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6096 if (!newuser) {
6097 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6098 err_code |= ERR_ALERT | ERR_ABORT;
6099 goto out;
6100 }
6101
6102 newuser->user = strdup(args[1]);
6103
6104 newuser->next = userlist->users;
6105 userlist->users = newuser;
6106
6107 cur_arg = 2;
6108
6109 while (*args[cur_arg]) {
6110 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006111#ifdef CONFIG_HAP_CRYPT
6112 if (!crypt("", args[cur_arg + 1])) {
6113 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6114 file, linenum, newuser->user);
6115 err_code |= ERR_ALERT | ERR_FATAL;
6116 goto out;
6117 }
6118#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006119 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6120 file, linenum);
6121 err_code |= ERR_ALERT;
6122#endif
6123 newuser->pass = strdup(args[cur_arg + 1]);
6124 cur_arg += 2;
6125 continue;
6126 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6127 newuser->pass = strdup(args[cur_arg + 1]);
6128 newuser->flags |= AU_O_INSECURE;
6129 cur_arg += 2;
6130 continue;
6131 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006132 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006133 cur_arg += 2;
6134 continue;
6135 } else {
6136 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6137 file, linenum, args[0]);
6138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
6140 }
6141 }
6142 } else {
6143 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6144 err_code |= ERR_ALERT | ERR_FATAL;
6145 }
6146
6147out:
6148 return err_code;
6149}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006150
6151/*
6152 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006153 * Returns the error code, 0 if OK, or any combination of :
6154 * - ERR_ABORT: must abort ASAP
6155 * - ERR_FATAL: we can continue parsing but not start the service
6156 * - ERR_WARN: a warning has been emitted
6157 * - ERR_ALERT: an alert has been emitted
6158 * Only the two first ones can stop processing, the two others are just
6159 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006160 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006161int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006163 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 FILE *f;
6165 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006166 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006167 struct cfg_section *cs = NULL;
6168 struct cfg_section *ics;
6169
6170 /* Register internal sections */
6171 if (!cfg_register_section("listen", cfg_parse_listen) ||
6172 !cfg_register_section("frontend", cfg_parse_listen) ||
6173 !cfg_register_section("backend", cfg_parse_listen) ||
6174 !cfg_register_section("ruleset", cfg_parse_listen) ||
6175 !cfg_register_section("defaults", cfg_parse_listen) ||
6176 !cfg_register_section("global", cfg_parse_global) ||
6177 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006178 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006179 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006180 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006181 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006182
Willy Tarreaubaaee002006-06-26 02:48:02 +02006183 if ((f=fopen(file,"r")) == NULL)
6184 return -1;
6185
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006186 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006187 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006188 char *end;
6189 char *args[MAX_LINE_ARGS + 1];
6190 char *line = thisline;
6191
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192 linenum++;
6193
6194 end = line + strlen(line);
6195
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006196 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6197 /* Check if we reached the limit and the last char is not \n.
6198 * Watch out for the last line without the terminating '\n'!
6199 */
6200 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006201 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006202 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006203 }
6204
Willy Tarreaubaaee002006-06-26 02:48:02 +02006205 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006206 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006207 line++;
6208
6209 arg = 0;
6210 args[arg] = line;
6211
6212 while (*line && arg < MAX_LINE_ARGS) {
6213 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6214 * C equivalent value. Other combinations left unchanged (eg: \1).
6215 */
6216 if (*line == '\\') {
6217 int skip = 0;
6218 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6219 *line = line[1];
6220 skip = 1;
6221 }
6222 else if (line[1] == 'r') {
6223 *line = '\r';
6224 skip = 1;
6225 }
6226 else if (line[1] == 'n') {
6227 *line = '\n';
6228 skip = 1;
6229 }
6230 else if (line[1] == 't') {
6231 *line = '\t';
6232 skip = 1;
6233 }
6234 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006235 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006236 unsigned char hex1, hex2;
6237 hex1 = toupper(line[2]) - '0';
6238 hex2 = toupper(line[3]) - '0';
6239 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6240 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6241 *line = (hex1<<4) + hex2;
6242 skip = 3;
6243 }
6244 else {
6245 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006246 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006247 }
6248 }
6249 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006250 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006251 end -= skip;
6252 }
6253 line++;
6254 }
6255 else if (*line == '#' || *line == '\n' || *line == '\r') {
6256 /* end of string, end of loop */
6257 *line = 0;
6258 break;
6259 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006260 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006262 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006263 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006264 line++;
6265 args[++arg] = line;
6266 }
6267 else {
6268 line++;
6269 }
6270 }
6271
6272 /* empty line */
6273 if (!**args)
6274 continue;
6275
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006276 if (*line) {
6277 /* we had to stop due to too many args.
6278 * Let's terminate the string, print the offending part then cut the
6279 * last arg.
6280 */
6281 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6282 line++;
6283 *line = '\0';
6284
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006285 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006286 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006287 err_code |= ERR_ALERT | ERR_FATAL;
6288 args[arg] = line;
6289 }
6290
Willy Tarreau540abe42007-05-02 20:50:16 +02006291 /* zero out remaining args and ensure that at least one entry
6292 * is zeroed out.
6293 */
6294 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 args[arg] = line;
6296 }
6297
Willy Tarreau3842f002009-06-14 11:39:52 +02006298 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006299 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006300 char *tmp;
6301
Willy Tarreau3842f002009-06-14 11:39:52 +02006302 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006303 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006304 for (arg=0; *args[arg+1]; arg++)
6305 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006306 *tmp = '\0'; // fix the next arg to \0
6307 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006308 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006309 else if (!strcmp(args[0], "default")) {
6310 kwm = KWM_DEF;
6311 for (arg=0; *args[arg+1]; arg++)
6312 args[arg] = args[arg+1]; // shift args after inversion
6313 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006314
William Lallemand0f99e342011-10-12 17:50:54 +02006315 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6316 strcmp(args[0], "log") != 0) {
6317 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006318 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006319 }
6320
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006321 /* detect section start */
6322 list_for_each_entry(ics, &sections, list) {
6323 if (strcmp(args[0], ics->section_name) == 0) {
6324 cursection = ics->section_name;
6325 cs = ics;
6326 break;
6327 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006328 }
6329
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006331 if (cs)
6332 err_code |= cs->section_parser(file, linenum, args, kwm);
6333 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006334 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006335 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006336 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006337
6338 if (err_code & ERR_ABORT)
6339 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006341 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006343 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006344}
6345
Willy Tarreau64ab6072014-09-16 12:17:36 +02006346/* This function propagates processes from frontend <from> to backend <to> so
6347 * that it is always guaranteed that a backend pointed to by a frontend is
6348 * bound to all of its processes. After that, if the target is a "listen"
6349 * instance, the function recursively descends the target's own targets along
6350 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6351 * checked first to ensure that <to> is already bound to all processes of
6352 * <from>, there is no risk of looping and we ensure to follow the shortest
6353 * path to the destination.
6354 *
6355 * It is possible to set <to> to NULL for the first call so that the function
6356 * takes care of visiting the initial frontend in <from>.
6357 *
6358 * It is important to note that the function relies on the fact that all names
6359 * have already been resolved.
6360 */
6361void propagate_processes(struct proxy *from, struct proxy *to)
6362{
6363 struct switching_rule *rule;
6364 struct hdr_exp *exp;
6365
6366 if (to) {
6367 /* check whether we need to go down */
6368 if (from->bind_proc &&
6369 (from->bind_proc & to->bind_proc) == from->bind_proc)
6370 return;
6371
6372 if (!from->bind_proc && !to->bind_proc)
6373 return;
6374
6375 to->bind_proc = from->bind_proc ?
6376 (to->bind_proc | from->bind_proc) : 0;
6377
6378 /* now propagate down */
6379 from = to;
6380 }
6381
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006382 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006383 return;
6384
Willy Tarreauf6b70012014-12-18 14:00:43 +01006385 if (from->state == PR_STSTOPPED)
6386 return;
6387
Willy Tarreau64ab6072014-09-16 12:17:36 +02006388 /* default_backend */
6389 if (from->defbe.be)
6390 propagate_processes(from, from->defbe.be);
6391
6392 /* use_backend */
6393 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006394 if (rule->dynamic)
6395 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006396 to = rule->be.backend;
6397 propagate_processes(from, to);
6398 }
6399
6400 /* reqsetbe */
6401 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6402 if (exp->action != ACT_SETBE)
6403 continue;
6404 to = (struct proxy *)exp->replace;
6405 propagate_processes(from, to);
6406 }
6407}
6408
Willy Tarreaubb925012009-07-23 13:36:36 +02006409/*
6410 * Returns the error code, 0 if OK, or any combination of :
6411 * - ERR_ABORT: must abort ASAP
6412 * - ERR_FATAL: we can continue parsing but not start the service
6413 * - ERR_WARN: a warning has been emitted
6414 * - ERR_ALERT: an alert has been emitted
6415 * Only the two first ones can stop processing, the two others are just
6416 * indicators.
6417 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006418int check_config_validity()
6419{
6420 int cfgerr = 0;
6421 struct proxy *curproxy = NULL;
6422 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006423 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006424 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006425 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006427 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006428 /*
6429 * Now, check for the integrity of all that we have collected.
6430 */
6431
6432 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006433 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434
Willy Tarreau193b8c62012-11-22 00:17:38 +01006435 if (!global.tune.max_http_hdr)
6436 global.tune.max_http_hdr = MAX_HTTP_HDR;
6437
6438 if (!global.tune.cookie_len)
6439 global.tune.cookie_len = CAPTURE_LEN;
6440
6441 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6442
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006443 /* Post initialisation of the users and groups lists. */
6444 err_code = userlist_postinit();
6445 if (err_code != ERR_NONE)
6446 goto out;
6447
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006448 /* first, we will invert the proxy list order */
6449 curproxy = NULL;
6450 while (proxy) {
6451 struct proxy *next;
6452
6453 next = proxy->next;
6454 proxy->next = curproxy;
6455 curproxy = proxy;
6456 if (!next)
6457 break;
6458 proxy = next;
6459 }
6460
Willy Tarreau419ead82014-09-16 13:41:21 +02006461 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006462 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006463 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006464 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006465 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006466 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006467 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006468 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006469
Willy Tarreau050536d2012-10-04 08:47:34 +02006470 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006471 /* proxy ID not set, use automatic numbering with first
6472 * spare entry starting with next_pxid.
6473 */
6474 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6475 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6476 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006477 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006478 next_pxid++;
6479
Willy Tarreau55ea7572007-06-17 19:56:27 +02006480
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006482 /* ensure we don't keep listeners uselessly bound */
6483 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006484 continue;
6485 }
6486
Willy Tarreau102df612014-05-07 23:56:38 +02006487 /* Check multi-process mode compatibility for the current proxy */
6488
6489 if (curproxy->bind_proc) {
6490 /* an explicit bind-process was specified, let's check how many
6491 * processes remain.
6492 */
6493 nbproc = popcount(curproxy->bind_proc);
6494
6495 curproxy->bind_proc &= nbits(global.nbproc);
6496 if (!curproxy->bind_proc && nbproc == 1) {
6497 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);
6498 curproxy->bind_proc = 1;
6499 }
6500 else if (!curproxy->bind_proc && nbproc > 1) {
6501 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);
6502 curproxy->bind_proc = 0;
6503 }
6504 }
6505
Willy Tarreau3d209582014-05-09 17:06:11 +02006506 /* check and reduce the bind-proc of each listener */
6507 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6508 unsigned long mask;
6509
6510 if (!bind_conf->bind_proc)
6511 continue;
6512
6513 mask = nbits(global.nbproc);
6514 if (curproxy->bind_proc)
6515 mask &= curproxy->bind_proc;
6516 /* mask cannot be null here thanks to the previous checks */
6517
6518 nbproc = popcount(bind_conf->bind_proc);
6519 bind_conf->bind_proc &= mask;
6520
6521 if (!bind_conf->bind_proc && nbproc == 1) {
6522 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",
6523 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6524 bind_conf->bind_proc = mask & ~(mask - 1);
6525 }
6526 else if (!bind_conf->bind_proc && nbproc > 1) {
6527 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",
6528 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6529 bind_conf->bind_proc = 0;
6530 }
6531 }
6532
Willy Tarreau102df612014-05-07 23:56:38 +02006533 if (global.nbproc > 1 && curproxy->table.peers.name) {
6534 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6535 curproxy->id);
6536 cfgerr++;
6537 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006538
Willy Tarreauff01a212009-03-15 13:46:16 +01006539 switch (curproxy->mode) {
6540 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006541 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006542 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006543 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6544 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006545 cfgerr++;
6546 }
6547
6548 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006549 Warning("config : servers will be ignored for %s '%s'.\n",
6550 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006551 break;
6552
6553 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006554 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006555 break;
6556
6557 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006558 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006559 break;
6560 }
6561
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006562 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006563 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006564 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006565 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6566 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006567 cfgerr++;
6568 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006569#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006570 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006571 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6572 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006573 cfgerr++;
6574 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006575#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006576 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006577 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6578 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006579 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006580 }
6581 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006582 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006583 /* If no LB algo is set in a backend, and we're not in
6584 * transparent mode, dispatch mode nor proxy mode, we
6585 * want to use balance roundrobin by default.
6586 */
6587 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6588 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006589 }
6590 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006591
Willy Tarreau1620ec32011-08-06 17:05:02 +02006592 if (curproxy->options & PR_O_DISPATCH)
6593 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6594 else if (curproxy->options & PR_O_HTTP_PROXY)
6595 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6596 else if (curproxy->options & PR_O_TRANSP)
6597 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006598
Willy Tarreau1620ec32011-08-06 17:05:02 +02006599 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6600 if (curproxy->options & PR_O_DISABLE404) {
6601 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6602 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6603 err_code |= ERR_WARN;
6604 curproxy->options &= ~PR_O_DISABLE404;
6605 }
6606 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6607 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6608 "send-state", proxy_type_str(curproxy), curproxy->id);
6609 err_code |= ERR_WARN;
6610 curproxy->options &= ~PR_O2_CHK_SNDST;
6611 }
Willy Tarreauef781042010-01-27 11:53:01 +01006612 }
6613
Simon Horman98637e52014-06-20 12:30:16 +09006614 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6615 if (!global.external_check) {
6616 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6617 curproxy->id, "option external-check");
6618 cfgerr++;
6619 }
6620 if (!curproxy->check_command) {
6621 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6622 curproxy->id, "option external-check");
6623 cfgerr++;
6624 }
6625 }
6626
Simon Horman64e34162015-02-06 11:11:57 +09006627 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006628 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6629 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006630 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6631 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006632 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6633 "to be present).\n",
6634 proxy_type_str(curproxy), curproxy->id);
6635 err_code |= ERR_WARN;
6636 free_email_alert(curproxy);
6637 }
6638 if (!curproxy->email_alert.myhostname)
6639 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006640 }
6641
Simon Horman98637e52014-06-20 12:30:16 +09006642 if (curproxy->check_command) {
6643 int clear = 0;
6644 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6645 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6646 "external-check command", proxy_type_str(curproxy), curproxy->id);
6647 err_code |= ERR_WARN;
6648 clear = 1;
6649 }
6650 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6651 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6652 curproxy->id, "external-check command");
6653 cfgerr++;
6654 }
6655 if (clear) {
6656 free(curproxy->check_command);
6657 curproxy->check_command = NULL;
6658 }
6659 }
6660
6661 if (curproxy->check_path) {
6662 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6663 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6664 "external-check path", proxy_type_str(curproxy), curproxy->id);
6665 err_code |= ERR_WARN;
6666 free(curproxy->check_path);
6667 curproxy->check_path = NULL;
6668 }
6669 }
6670
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006671 /* if a default backend was specified, let's find it */
6672 if (curproxy->defbe.name) {
6673 struct proxy *target;
6674
Alex Williams96532db2009-11-01 21:27:13 -05006675 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006676 if (!target) {
6677 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6678 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006679 cfgerr++;
6680 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006681 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6682 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006683 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006684 } else {
6685 free(curproxy->defbe.name);
6686 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006687
6688 /* Emit a warning if this proxy also has some servers */
6689 if (curproxy->srv) {
6690 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6691 curproxy->id);
6692 err_code |= ERR_WARN;
6693 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006694 }
6695 }
6696
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006697 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006698 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6699 /* map jump target for ACT_SETBE in req_rep chain */
6700 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006701 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006702 struct proxy *target;
6703
Willy Tarreaua496b602006-12-17 23:15:24 +01006704 if (exp->action != ACT_SETBE)
6705 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006706
Alex Williams96532db2009-11-01 21:27:13 -05006707 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006708 if (!target) {
6709 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6710 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006711 cfgerr++;
6712 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006713 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6714 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006715 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006716 } else {
6717 free((void *)exp->replace);
6718 exp->replace = (const char *)target;
6719 }
6720 }
6721 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006722
6723 /* find the target proxy for 'use_backend' rules */
6724 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006725 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006726 struct logformat_node *node;
6727 char *pxname;
6728
6729 /* Try to parse the string as a log format expression. If the result
6730 * of the parsing is only one entry containing a simple string, then
6731 * it's a standard string corresponding to a static rule, thus the
6732 * parsing is cancelled and be.name is restored to be resolved.
6733 */
6734 pxname = rule->be.name;
6735 LIST_INIT(&rule->be.expr);
6736 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6737 curproxy->conf.args.file, curproxy->conf.args.line);
6738 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6739
6740 if (!LIST_ISEMPTY(&rule->be.expr)) {
6741 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6742 rule->dynamic = 1;
6743 free(pxname);
6744 continue;
6745 }
6746 /* simple string: free the expression and fall back to static rule */
6747 free(node->arg);
6748 free(node);
6749 }
6750
6751 rule->dynamic = 0;
6752 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006753
Alex Williams96532db2009-11-01 21:27:13 -05006754 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006755
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006756 if (!target) {
6757 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6758 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006759 cfgerr++;
6760 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006761 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6762 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006763 cfgerr++;
6764 } else {
6765 free((void *)rule->be.name);
6766 rule->be.backend = target;
6767 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006768 }
6769
Willy Tarreau64ab6072014-09-16 12:17:36 +02006770 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006771 list_for_each_entry(srule, &curproxy->server_rules, list) {
6772 struct server *target = findserver(curproxy, srule->srv.name);
6773
6774 if (!target) {
6775 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6776 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6777 cfgerr++;
6778 continue;
6779 }
6780 free((void *)srule->srv.name);
6781 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006782 }
6783
Emeric Brunb982a3d2010-01-04 15:45:53 +01006784 /* find the target table for 'stick' rules */
6785 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6786 struct proxy *target;
6787
Emeric Brun1d33b292010-01-04 15:47:17 +01006788 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6789 if (mrule->flags & STK_IS_STORE)
6790 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6791
Emeric Brunb982a3d2010-01-04 15:45:53 +01006792 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006793 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006794 else
6795 target = curproxy;
6796
6797 if (!target) {
6798 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6799 curproxy->id, mrule->table.name);
6800 cfgerr++;
6801 }
6802 else if (target->table.size == 0) {
6803 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6804 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6805 cfgerr++;
6806 }
Willy Tarreau12785782012-04-27 21:37:17 +02006807 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6808 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006809 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6810 cfgerr++;
6811 }
6812 else {
6813 free((void *)mrule->table.name);
6814 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006815 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006816 }
6817 }
6818
6819 /* find the target table for 'store response' rules */
6820 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6821 struct proxy *target;
6822
Emeric Brun1d33b292010-01-04 15:47:17 +01006823 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6824
Emeric Brunb982a3d2010-01-04 15:45:53 +01006825 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006826 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006827 else
6828 target = curproxy;
6829
6830 if (!target) {
6831 Alert("Proxy '%s': unable to find store table '%s'.\n",
6832 curproxy->id, mrule->table.name);
6833 cfgerr++;
6834 }
6835 else if (target->table.size == 0) {
6836 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6837 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6838 cfgerr++;
6839 }
Willy Tarreau12785782012-04-27 21:37:17 +02006840 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6841 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006842 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6843 cfgerr++;
6844 }
6845 else {
6846 free((void *)mrule->table.name);
6847 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006848 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006849 }
6850 }
6851
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006852 /* find the target table for 'tcp-request' layer 4 rules */
6853 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6854 struct proxy *target;
6855
Willy Tarreaub4c84932013-07-23 19:15:30 +02006856 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006857 continue;
6858
6859 if (trule->act_prm.trk_ctr.table.n)
6860 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6861 else
6862 target = curproxy;
6863
6864 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006865 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6866 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006867 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006868 cfgerr++;
6869 }
6870 else if (target->table.size == 0) {
6871 Alert("Proxy '%s': table '%s' used but not configured.\n",
6872 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6873 cfgerr++;
6874 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006875 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6876 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6877 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 +01006878 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006879 cfgerr++;
6880 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006881 else {
6882 free(trule->act_prm.trk_ctr.table.n);
6883 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006884 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006885 * to pass a list of counters to track and allocate them right here using
6886 * stktable_alloc_data_type().
6887 */
6888 }
6889 }
6890
Willy Tarreaud1f96522010-08-03 19:34:32 +02006891 /* find the target table for 'tcp-request' layer 6 rules */
6892 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6893 struct proxy *target;
6894
Willy Tarreaub4c84932013-07-23 19:15:30 +02006895 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006896 continue;
6897
6898 if (trule->act_prm.trk_ctr.table.n)
6899 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6900 else
6901 target = curproxy;
6902
6903 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006904 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6905 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006906 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006907 cfgerr++;
6908 }
6909 else if (target->table.size == 0) {
6910 Alert("Proxy '%s': table '%s' used but not configured.\n",
6911 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6912 cfgerr++;
6913 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006914 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6915 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6916 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 +01006917 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006918 cfgerr++;
6919 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006920 else {
6921 free(trule->act_prm.trk_ctr.table.n);
6922 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006923 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006924 * to pass a list of counters to track and allocate them right here using
6925 * stktable_alloc_data_type().
6926 */
6927 }
6928 }
6929
Willy Tarreau09448f72014-06-25 18:12:15 +02006930 /* find the target table for 'http-request' layer 7 rules */
6931 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6932 struct proxy *target;
6933
6934 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6935 continue;
6936
6937 if (hrqrule->act_prm.trk_ctr.table.n)
6938 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6939 else
6940 target = curproxy;
6941
6942 if (!target) {
6943 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6944 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6945 http_req_trk_idx(hrqrule->action));
6946 cfgerr++;
6947 }
6948 else if (target->table.size == 0) {
6949 Alert("Proxy '%s': table '%s' used but not configured.\n",
6950 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6951 cfgerr++;
6952 }
6953 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6954 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6955 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6956 http_req_trk_idx(hrqrule->action));
6957 cfgerr++;
6958 }
6959 else {
6960 free(hrqrule->act_prm.trk_ctr.table.n);
6961 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6962 /* Note: if we decide to enhance the track-sc syntax, we may be able
6963 * to pass a list of counters to track and allocate them right here using
6964 * stktable_alloc_data_type().
6965 */
6966 }
6967 }
6968
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006969 /* move any "block" rules at the beginning of the http-request rules */
6970 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6971 /* insert block_rules into http_req_rules at the beginning */
6972 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6973 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6974 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6975 curproxy->http_req_rules.n = curproxy->block_rules.n;
6976 LIST_INIT(&curproxy->block_rules);
6977 }
6978
Emeric Brun32da3c42010-09-23 18:39:19 +02006979 if (curproxy->table.peers.name) {
6980 struct peers *curpeers = peers;
6981
6982 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6983 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6984 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006985 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006986 break;
6987 }
6988 }
6989
6990 if (!curpeers) {
6991 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6992 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006993 free((void *)curproxy->table.peers.name);
6994 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006995 cfgerr++;
6996 }
6997 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006998 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6999 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007000 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007001 cfgerr++;
7002 }
7003 }
7004
Simon Horman9dc49962015-01-30 11:22:59 +09007005
7006 if (curproxy->email_alert.mailers.name) {
7007 struct mailers *curmailers = mailers;
7008
7009 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7010 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7011 free(curproxy->email_alert.mailers.name);
7012 curproxy->email_alert.mailers.m = curmailers;
7013 curmailers->users++;
7014 break;
7015 }
7016 }
7017
7018 if (!curmailers) {
7019 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7020 curproxy->id, curproxy->email_alert.mailers.name);
7021 free_email_alert(curproxy);
7022 cfgerr++;
7023 }
7024 }
7025
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007026 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007027 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007028 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7029 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7030 "proxy", curproxy->id);
7031 cfgerr++;
7032 goto out_uri_auth_compat;
7033 }
7034
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007035 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007036 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007037 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007038 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007039
Willy Tarreau95fa4692010-02-01 13:05:50 +01007040 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7041 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007042
7043 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007044 uri_auth_compat_req[i++] = "realm";
7045 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7046 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007047
Willy Tarreau95fa4692010-02-01 13:05:50 +01007048 uri_auth_compat_req[i++] = "unless";
7049 uri_auth_compat_req[i++] = "{";
7050 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7051 uri_auth_compat_req[i++] = "}";
7052 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007053
Willy Tarreauff011f22011-01-06 17:51:27 +01007054 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7055 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007056 cfgerr++;
7057 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007058 }
7059
Willy Tarreauff011f22011-01-06 17:51:27 +01007060 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007061
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007062 if (curproxy->uri_auth->auth_realm) {
7063 free(curproxy->uri_auth->auth_realm);
7064 curproxy->uri_auth->auth_realm = NULL;
7065 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007066
7067 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007068 }
7069out_uri_auth_compat:
7070
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007071 /* compile the log format */
7072 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007073 if (curproxy->conf.logformat_string != default_http_log_format &&
7074 curproxy->conf.logformat_string != default_tcp_log_format &&
7075 curproxy->conf.logformat_string != clf_http_log_format)
7076 free(curproxy->conf.logformat_string);
7077 curproxy->conf.logformat_string = NULL;
7078 free(curproxy->conf.lfs_file);
7079 curproxy->conf.lfs_file = NULL;
7080 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007081 }
7082
Willy Tarreau62a61232013-04-12 18:13:46 +02007083 if (curproxy->conf.logformat_string) {
7084 curproxy->conf.args.ctx = ARGC_LOG;
7085 curproxy->conf.args.file = curproxy->conf.lfs_file;
7086 curproxy->conf.args.line = curproxy->conf.lfs_line;
7087 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007088 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007089 curproxy->conf.args.file = NULL;
7090 curproxy->conf.args.line = 0;
7091 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007092
Willy Tarreau62a61232013-04-12 18:13:46 +02007093 if (curproxy->conf.uniqueid_format_string) {
7094 curproxy->conf.args.ctx = ARGC_UIF;
7095 curproxy->conf.args.file = curproxy->conf.uif_file;
7096 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007097 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007098 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007099 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007100 curproxy->conf.args.file = NULL;
7101 curproxy->conf.args.line = 0;
7102 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007103
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007104 /* only now we can check if some args remain unresolved.
7105 * This must be done after the users and groups resolution.
7106 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007107 cfgerr += smp_resolve_args(curproxy);
7108 if (!cfgerr)
7109 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007110
Willy Tarreau2738a142006-07-08 17:28:09 +02007111 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007112 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007113 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007114 (!curproxy->timeout.connect ||
7115 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007116 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007117 " | While not properly invalid, you will certainly encounter various problems\n"
7118 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007119 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007120 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007121 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007122 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007123
Willy Tarreau1fa31262007-12-03 00:36:16 +01007124 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7125 * We must still support older configurations, so let's find out whether those
7126 * parameters have been set or must be copied from contimeouts.
7127 */
7128 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007129 if (!curproxy->timeout.tarpit ||
7130 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007131 /* tarpit timeout not set. We search in the following order:
7132 * default.tarpit, curr.connect, default.connect.
7133 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007134 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007135 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007136 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007137 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007138 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007139 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007140 }
7141 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007142 (!curproxy->timeout.queue ||
7143 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007144 /* queue timeout not set. We search in the following order:
7145 * default.queue, curr.connect, default.connect.
7146 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007147 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007148 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007149 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007150 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007151 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007152 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007153 }
7154 }
7155
Willy Tarreau1620ec32011-08-06 17:05:02 +02007156 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007157 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7158 curproxy->check_req = (char *)malloc(curproxy->check_len);
7159 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007160 }
7161
Willy Tarreau215663d2014-06-13 18:30:23 +02007162 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7163 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7164 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7165 proxy_type_str(curproxy), curproxy->id);
7166 err_code |= ERR_WARN;
7167 }
7168
Willy Tarreau193b8c62012-11-22 00:17:38 +01007169 /* ensure that cookie capture length is not too large */
7170 if (curproxy->capture_len >= global.tune.cookie_len) {
7171 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7172 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7173 err_code |= ERR_WARN;
7174 curproxy->capture_len = global.tune.cookie_len - 1;
7175 }
7176
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007177 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007178 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007179 curproxy->req_cap_pool = create_pool("ptrcap",
7180 curproxy->nb_req_cap * sizeof(char *),
7181 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007182 }
7183
7184 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007185 curproxy->rsp_cap_pool = create_pool("ptrcap",
7186 curproxy->nb_rsp_cap * sizeof(char *),
7187 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007188 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007189
Willy Tarreaubaaee002006-06-26 02:48:02 +02007190 /* first, we will invert the servers list order */
7191 newsrv = NULL;
7192 while (curproxy->srv) {
7193 struct server *next;
7194
7195 next = curproxy->srv->next;
7196 curproxy->srv->next = newsrv;
7197 newsrv = curproxy->srv;
7198 if (!next)
7199 break;
7200 curproxy->srv = next;
7201 }
7202
Willy Tarreau17edc812014-01-03 12:14:34 +01007203 /* Check that no server name conflicts. This causes trouble in the stats.
7204 * We only emit a warning for the first conflict affecting each server,
7205 * in order to avoid combinatory explosion if all servers have the same
7206 * name. We do that only for servers which do not have an explicit ID,
7207 * because these IDs were made also for distinguishing them and we don't
7208 * want to annoy people who correctly manage them.
7209 */
7210 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7211 struct server *other_srv;
7212
7213 if (newsrv->puid)
7214 continue;
7215
7216 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7217 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7218 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7219 newsrv->conf.file, newsrv->conf.line,
7220 proxy_type_str(curproxy), curproxy->id,
7221 newsrv->id, other_srv->conf.line);
7222 break;
7223 }
7224 }
7225 }
7226
Willy Tarreaudd701652010-05-25 23:03:02 +02007227 /* assign automatic UIDs to servers which don't have one yet */
7228 next_id = 1;
7229 newsrv = curproxy->srv;
7230 while (newsrv != NULL) {
7231 if (!newsrv->puid) {
7232 /* server ID not set, use automatic numbering with first
7233 * spare entry starting with next_svid.
7234 */
7235 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7236 newsrv->conf.id.key = newsrv->puid = next_id;
7237 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7238 }
7239 next_id++;
7240 newsrv = newsrv->next;
7241 }
7242
Willy Tarreau20697042007-11-15 23:26:18 +01007243 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007244 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007245
Willy Tarreau62c3be22012-01-20 13:12:32 +01007246 /*
7247 * If this server supports a maxconn parameter, it needs a dedicated
7248 * tasks to fill the emptied slots when a connection leaves.
7249 * Also, resolve deferred tracking dependency if needed.
7250 */
7251 newsrv = curproxy->srv;
7252 while (newsrv != NULL) {
7253 if (newsrv->minconn > newsrv->maxconn) {
7254 /* Only 'minconn' was specified, or it was higher than or equal
7255 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7256 * this will avoid further useless expensive computations.
7257 */
7258 newsrv->maxconn = newsrv->minconn;
7259 } else if (newsrv->maxconn && !newsrv->minconn) {
7260 /* minconn was not specified, so we set it to maxconn */
7261 newsrv->minconn = newsrv->maxconn;
7262 }
7263
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007264#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007265 if (newsrv->use_ssl || newsrv->check.use_ssl)
7266 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007267#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007268
Willy Tarreau2f075e92013-12-03 11:11:34 +01007269 /* set the check type on the server */
7270 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7271
Willy Tarreau62c3be22012-01-20 13:12:32 +01007272 if (newsrv->trackit) {
7273 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007274 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007275 char *pname, *sname;
7276
7277 pname = newsrv->trackit;
7278 sname = strrchr(pname, '/');
7279
7280 if (sname)
7281 *sname++ = '\0';
7282 else {
7283 sname = pname;
7284 pname = NULL;
7285 }
7286
7287 if (pname) {
7288 px = findproxy(pname, PR_CAP_BE);
7289 if (!px) {
7290 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7291 proxy_type_str(curproxy), curproxy->id,
7292 newsrv->id, pname);
7293 cfgerr++;
7294 goto next_srv;
7295 }
7296 } else
7297 px = curproxy;
7298
7299 srv = findserver(px, sname);
7300 if (!srv) {
7301 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7302 proxy_type_str(curproxy), curproxy->id,
7303 newsrv->id, sname);
7304 cfgerr++;
7305 goto next_srv;
7306 }
7307
Willy Tarreau32091232014-05-16 13:52:00 +02007308 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7309 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7310 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007311 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007312 "tracking as it does not have any check nor agent enabled.\n",
7313 proxy_type_str(curproxy), curproxy->id,
7314 newsrv->id, px->id, srv->id);
7315 cfgerr++;
7316 goto next_srv;
7317 }
7318
7319 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7320
7321 if (loop) {
7322 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7323 "belongs to a tracking chain looping back to %s/%s.\n",
7324 proxy_type_str(curproxy), curproxy->id,
7325 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007326 cfgerr++;
7327 goto next_srv;
7328 }
7329
7330 if (curproxy != px &&
7331 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7332 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7333 "tracking: disable-on-404 option inconsistency.\n",
7334 proxy_type_str(curproxy), curproxy->id,
7335 newsrv->id, px->id, srv->id);
7336 cfgerr++;
7337 goto next_srv;
7338 }
7339
7340 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007341 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007342 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007343 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007344 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007345 }
7346
7347 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007348 newsrv->tracknext = srv->trackers;
7349 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007350
7351 free(newsrv->trackit);
7352 newsrv->trackit = NULL;
7353 }
7354 next_srv:
7355 newsrv = newsrv->next;
7356 }
7357
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007358 /* We have to initialize the server lookup mechanism depending
7359 * on what LB algorithm was choosen.
7360 */
7361
7362 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7363 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7364 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007365 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7366 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7367 init_server_map(curproxy);
7368 } else {
7369 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7370 fwrr_init_server_groups(curproxy);
7371 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007372 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007373
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007374 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007375 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7376 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7377 fwlc_init_server_tree(curproxy);
7378 } else {
7379 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7380 fas_init_server_tree(curproxy);
7381 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007382 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007383
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007384 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007385 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7386 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7387 chash_init_server_tree(curproxy);
7388 } else {
7389 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7390 init_server_map(curproxy);
7391 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007392 break;
7393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007394
7395 if (curproxy->options & PR_O_LOGASAP)
7396 curproxy->to_log &= ~LW_BYTES;
7397
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007398 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007399 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007400 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7401 proxy_type_str(curproxy), curproxy->id);
7402 err_code |= ERR_WARN;
7403 }
7404
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007405 if (curproxy->mode != PR_MODE_HTTP) {
7406 int optnum;
7407
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007408 if (curproxy->uri_auth) {
7409 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7410 proxy_type_str(curproxy), curproxy->id);
7411 err_code |= ERR_WARN;
7412 curproxy->uri_auth = NULL;
7413 }
7414
Willy Tarreau87cf5142011-08-19 22:57:24 +02007415 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007416 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7417 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7418 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007419 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007420 }
7421
7422 if (curproxy->options & PR_O_ORGTO) {
7423 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7424 "originalto", proxy_type_str(curproxy), curproxy->id);
7425 err_code |= ERR_WARN;
7426 curproxy->options &= ~PR_O_ORGTO;
7427 }
7428
7429 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7430 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7431 (curproxy->cap & cfg_opts[optnum].cap) &&
7432 (curproxy->options & cfg_opts[optnum].val)) {
7433 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7434 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7435 err_code |= ERR_WARN;
7436 curproxy->options &= ~cfg_opts[optnum].val;
7437 }
7438 }
7439
7440 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7441 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7442 (curproxy->cap & cfg_opts2[optnum].cap) &&
7443 (curproxy->options2 & cfg_opts2[optnum].val)) {
7444 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7445 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7446 err_code |= ERR_WARN;
7447 curproxy->options2 &= ~cfg_opts2[optnum].val;
7448 }
7449 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007450
Pieter Baauwd551fb52013-05-08 22:49:23 +02007451#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007452 if (curproxy->conn_src.bind_hdr_occ) {
7453 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007454 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007455 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007456 err_code |= ERR_WARN;
7457 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007458#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007459 }
7460
Willy Tarreaubaaee002006-06-26 02:48:02 +02007461 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007462 * ensure that we're not cross-dressing a TCP server into HTTP.
7463 */
7464 newsrv = curproxy->srv;
7465 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007466 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007467 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7468 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007469 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007470 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007471
Willy Tarreau0cec3312011-10-31 13:49:26 +01007472 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7473 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7474 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7475 err_code |= ERR_WARN;
7476 }
7477
Willy Tarreauc93cd162014-05-13 15:54:22 +02007478 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007479 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7480 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7481 err_code |= ERR_WARN;
7482 }
7483
Pieter Baauwd551fb52013-05-08 22:49:23 +02007484#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007485 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7486 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007487 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 +01007488 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007489 err_code |= ERR_WARN;
7490 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007491#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007492 newsrv = newsrv->next;
7493 }
7494
Willy Tarreaue42bd962014-09-16 16:21:19 +02007495 /* check if we have a frontend with "tcp-request content" looking at L7
7496 * with no inspect-delay
7497 */
7498 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7499 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7500 if (trule->action == TCP_ACT_CAPTURE &&
7501 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7502 break;
7503 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7504 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7505 break;
7506 }
7507
7508 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7509 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7510 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7511 " This means that these rules will randomly find their contents. This can be fixed by"
7512 " setting the tcp-request inspect-delay.\n",
7513 proxy_type_str(curproxy), curproxy->id);
7514 err_code |= ERR_WARN;
7515 }
7516 }
7517
Willy Tarreauc1a21672009-08-16 22:37:44 +02007518 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007519 if (!curproxy->accept)
7520 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007521
Willy Tarreauc1a21672009-08-16 22:37:44 +02007522 if (curproxy->tcp_req.inspect_delay ||
7523 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007524 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007525
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007526 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007527 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007528 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007529 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007530
7531 /* both TCP and HTTP must check switching rules */
7532 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7533 }
7534
7535 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007536 if (curproxy->tcp_req.inspect_delay ||
7537 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7538 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7539
Emeric Brun97679e72010-09-23 17:56:44 +02007540 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7541 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7542
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007543 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007544 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007545 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007546 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007547
7548 /* If the backend does requires RDP cookie persistence, we have to
7549 * enable the corresponding analyser.
7550 */
7551 if (curproxy->options2 & PR_O2_RDPC_PRST)
7552 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7553 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007554 }
7555
7556 /***********************************************************/
7557 /* At this point, target names have already been resolved. */
7558 /***********************************************************/
7559
7560 /* Check multi-process mode compatibility */
7561
7562 if (global.nbproc > 1 && global.stats_fe) {
7563 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7564 unsigned long mask;
7565
7566 mask = nbits(global.nbproc);
7567 if (global.stats_fe->bind_proc)
7568 mask &= global.stats_fe->bind_proc;
7569
7570 if (bind_conf->bind_proc)
7571 mask &= bind_conf->bind_proc;
7572
7573 /* stop here if more than one process is used */
7574 if (popcount(mask) > 1)
7575 break;
7576 }
7577 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7578 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");
7579 }
7580 }
7581
7582 /* Make each frontend inherit bind-process from its listeners when not specified. */
7583 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7584 if (curproxy->bind_proc)
7585 continue;
7586
7587 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7588 unsigned long mask;
7589
7590 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7591 curproxy->bind_proc |= mask;
7592 }
7593
7594 if (!curproxy->bind_proc)
7595 curproxy->bind_proc = ~0UL;
7596 }
7597
7598 if (global.stats_fe) {
7599 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7600 unsigned long mask;
7601
7602 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7603 global.stats_fe->bind_proc |= mask;
7604 }
7605 if (!global.stats_fe->bind_proc)
7606 global.stats_fe->bind_proc = ~0UL;
7607 }
7608
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007609 /* propagate bindings from frontends to backends. Don't do it if there
7610 * are any fatal errors as we must not call it with unresolved proxies.
7611 */
7612 if (!cfgerr) {
7613 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7614 if (curproxy->cap & PR_CAP_FE)
7615 propagate_processes(curproxy, NULL);
7616 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007617 }
7618
7619 /* Bind each unbound backend to all processes when not specified. */
7620 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7621 if (curproxy->bind_proc)
7622 continue;
7623 curproxy->bind_proc = ~0UL;
7624 }
7625
7626 /*******************************************************/
7627 /* At this step, all proxies have a non-null bind_proc */
7628 /*******************************************************/
7629
7630 /* perform the final checks before creating tasks */
7631
7632 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7633 struct listener *listener;
7634 unsigned int next_id;
7635 int nbproc;
7636
7637 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007638
Emeric Brunc52962f2012-11-15 18:28:02 +01007639#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007640 /* Configure SSL for each bind line.
7641 * Note: if configuration fails at some point, the ->ctx member
7642 * remains NULL so that listeners can later detach.
7643 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007644 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007645 int alloc_ctx;
7646
Emeric Brunc52962f2012-11-15 18:28:02 +01007647 if (!bind_conf->is_ssl) {
7648 if (bind_conf->default_ctx) {
7649 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7650 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7651 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007652 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007653 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007654 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007655 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007656 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007657 cfgerr++;
7658 continue;
7659 }
7660
Emeric Brun8dc60392014-05-09 13:52:00 +02007661 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007662 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007663 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7664 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");
7665 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007666 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007667 cfgerr++;
7668 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007669 }
7670
Emeric Brunfc0421f2012-09-07 17:30:07 +02007671 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007672 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007673 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007674#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007675
Willy Tarreaue6b98942007-10-29 01:09:36 +01007676 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007677 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007678 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007679 if (!listener->luid) {
7680 /* listener ID not set, use automatic numbering with first
7681 * spare entry starting with next_luid.
7682 */
7683 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7684 listener->conf.id.key = listener->luid = next_id;
7685 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007686 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007687 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007688
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007689 /* enable separate counters */
7690 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7691 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007692 if (!listener->name)
7693 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007694 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007695
Willy Tarreaue6b98942007-10-29 01:09:36 +01007696 if (curproxy->options & PR_O_TCP_NOLING)
7697 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007698 if (!listener->maxconn)
7699 listener->maxconn = curproxy->maxconn;
7700 if (!listener->backlog)
7701 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007702 if (!listener->maxaccept)
7703 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7704
7705 /* we want to have an optimal behaviour on single process mode to
7706 * maximize the work at once, but in multi-process we want to keep
7707 * some fairness between processes, so we target half of the max
7708 * number of events to be balanced over all the processes the proxy
7709 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7710 * used to disable the limit.
7711 */
7712 if (listener->maxaccept > 0) {
7713 if (nbproc > 1)
7714 listener->maxaccept = (listener->maxaccept + 1) / 2;
7715 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7716 }
7717
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007718 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007719 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007720 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007721 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007722
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007723 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7724 listener->options |= LI_O_TCP_RULES;
7725
Willy Tarreaude3041d2010-05-31 10:56:17 +02007726 if (curproxy->mon_mask.s_addr)
7727 listener->options |= LI_O_CHK_MONNET;
7728
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007729 /* smart accept mode is automatic in HTTP mode */
7730 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007731 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007732 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7733 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007734 }
7735
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007736 /* Release unused SSL configs */
7737 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7738 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007739 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007740#ifdef USE_OPENSSL
7741 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007742 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007743 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007744 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007745 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007746 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007747#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007748 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007749
Willy Tarreau102df612014-05-07 23:56:38 +02007750 if (nbproc > 1) {
7751 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007752 int count, maxproc = 0;
7753
7754 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7755 count = popcount(bind_conf->bind_proc);
7756 if (count > maxproc)
7757 maxproc = count;
7758 }
7759 /* backends have 0, frontends have 1 or more */
7760 if (maxproc != 1)
7761 Warning("Proxy '%s': in multi-process mode, stats will be"
7762 " limited to process assigned to the current request.\n",
7763 curproxy->id);
7764
Willy Tarreau102df612014-05-07 23:56:38 +02007765 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7766 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7767 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007768 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007769 }
Willy Tarreau102df612014-05-07 23:56:38 +02007770 if (curproxy->appsession_name) {
7771 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7772 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007773 }
Willy Tarreau102df612014-05-07 23:56:38 +02007774 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7775 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7776 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007777 }
7778 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007779
7780 /* create the task associated with the proxy */
7781 curproxy->task = task_new();
7782 if (curproxy->task) {
7783 curproxy->task->context = curproxy;
7784 curproxy->task->process = manage_proxy;
7785 /* no need to queue, it will be done automatically if some
7786 * listener gets limited.
7787 */
7788 curproxy->task->expire = TICK_ETERNITY;
7789 } else {
7790 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7791 curproxy->id);
7792 cfgerr++;
7793 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007794 }
7795
Willy Tarreaufbb78422011-06-05 15:38:35 +02007796 /* automatically compute fullconn if not set. We must not do it in the
7797 * loop above because cross-references are not yet fully resolved.
7798 */
7799 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7800 /* If <fullconn> is not set, let's set it to 10% of the sum of
7801 * the possible incoming frontend's maxconns.
7802 */
7803 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7804 struct proxy *fe;
7805 int total = 0;
7806
7807 /* sum up the number of maxconns of frontends which
7808 * reference this backend at least once or which are
7809 * the same one ('listen').
7810 */
7811 for (fe = proxy; fe; fe = fe->next) {
7812 struct switching_rule *rule;
7813 struct hdr_exp *exp;
7814 int found = 0;
7815
7816 if (!(fe->cap & PR_CAP_FE))
7817 continue;
7818
7819 if (fe == curproxy) /* we're on a "listen" instance */
7820 found = 1;
7821
7822 if (fe->defbe.be == curproxy) /* "default_backend" */
7823 found = 1;
7824
7825 /* check if a "use_backend" rule matches */
7826 if (!found) {
7827 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007828 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007829 found = 1;
7830 break;
7831 }
7832 }
7833 }
7834
7835 /* check if a "reqsetbe" rule matches */
7836 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7837 if (exp->action == ACT_SETBE &&
7838 (struct proxy *)exp->replace == curproxy) {
7839 found = 1;
7840 break;
7841 }
7842 }
7843
7844 /* now we've checked all possible ways to reference a backend
7845 * from a frontend.
7846 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007847 if (!found)
7848 continue;
7849 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007850 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007851 /* we have the sum of the maxconns in <total>. We only
7852 * keep 10% of that sum to set the default fullconn, with
7853 * a hard minimum of 1 (to avoid a divide by zero).
7854 */
7855 curproxy->fullconn = (total + 9) / 10;
7856 if (!curproxy->fullconn)
7857 curproxy->fullconn = 1;
7858 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007859 }
7860
Willy Tarreau056f5682010-06-06 15:51:11 +02007861 /* initialize stick-tables on backend capable proxies. This must not
7862 * be done earlier because the data size may be discovered while parsing
7863 * other proxies.
7864 */
Godbach9703e662013-12-11 21:11:41 +08007865 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007866 if (curproxy->state == PR_STSTOPPED)
7867 continue;
7868
Godbach9703e662013-12-11 21:11:41 +08007869 if (!stktable_init(&curproxy->table)) {
7870 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7871 cfgerr++;
7872 }
7873 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007874
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007875 /*
7876 * Recount currently required checks.
7877 */
7878
7879 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7880 int optnum;
7881
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007882 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7883 if (curproxy->options & cfg_opts[optnum].val)
7884 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007885
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007886 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7887 if (curproxy->options2 & cfg_opts2[optnum].val)
7888 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007889 }
7890
Willy Tarreau122541c2011-09-07 21:24:49 +02007891 if (peers) {
7892 struct peers *curpeers = peers, **last;
7893 struct peer *p, *pb;
7894
7895 /* Remove all peers sections which don't have a valid listener.
7896 * This can happen when a peers section is never referenced and
7897 * does not contain a local peer.
7898 */
7899 last = &peers;
7900 while (*last) {
7901 curpeers = *last;
7902 if (curpeers->peers_fe) {
7903 last = &curpeers->next;
7904 continue;
7905 }
7906
7907 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7908 curpeers->id, localpeer);
7909
7910 p = curpeers->remote;
7911 while (p) {
7912 pb = p->next;
7913 free(p->id);
7914 free(p);
7915 p = pb;
7916 }
7917
7918 /* Destroy and unlink this curpeers section.
7919 * Note: curpeers is backed up into *last.
7920 */
7921 free(curpeers->id);
7922 curpeers = curpeers->next;
7923 free(*last);
7924 *last = curpeers;
7925 }
7926 }
7927
Simon Horman0d16a402015-01-30 11:22:58 +09007928 if (mailers) {
7929 struct mailers *curmailers = mailers, **last;
7930 struct mailer *m, *mb;
7931
7932 /* Remove all mailers sections which don't have a valid listener.
7933 * This can happen when a mailers section is never referenced.
7934 */
7935 last = &mailers;
7936 while (*last) {
7937 curmailers = *last;
7938 if (curmailers->users) {
7939 last = &curmailers->next;
7940 continue;
7941 }
7942
7943 Warning("Removing incomplete section 'mailers %s'.\n",
7944 curmailers->id);
7945
7946 m = curmailers->mailer_list;
7947 while (m) {
7948 mb = m->next;
7949 free(m->id);
7950 free(m);
7951 m = mb;
7952 }
7953
7954 /* Destroy and unlink this curmailers section.
7955 * Note: curmailers is backed up into *last.
7956 */
7957 free(curmailers->id);
7958 curmailers = curmailers->next;
7959 free(*last);
7960 *last = curmailers;
7961 }
7962 }
7963
Willy Tarreau34eb6712011-10-24 18:15:04 +02007964 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007965 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007966 MEM_F_SHARED);
7967
Willy Tarreaubb925012009-07-23 13:36:36 +02007968 if (cfgerr > 0)
7969 err_code |= ERR_ALERT | ERR_FATAL;
7970 out:
7971 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007972}
7973
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007974/*
7975 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7976 * parsing sessions.
7977 */
7978void cfg_register_keywords(struct cfg_kw_list *kwl)
7979{
7980 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7981}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007982
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007983/*
7984 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7985 */
7986void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7987{
7988 LIST_DEL(&kwl->list);
7989 LIST_INIT(&kwl->list);
7990}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007991
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007992/* this function register new section in the haproxy configuration file.
7993 * <section_name> is the name of this new section and <section_parser>
7994 * is the called parser. If two section declaration have the same name,
7995 * only the first declared is used.
7996 */
7997int cfg_register_section(char *section_name,
7998 int (*section_parser)(const char *, int, char **, int))
7999{
8000 struct cfg_section *cs;
8001
8002 cs = calloc(1, sizeof(*cs));
8003 if (!cs) {
8004 Alert("register section '%s': out of memory.\n", section_name);
8005 return 0;
8006 }
8007
8008 cs->section_name = section_name;
8009 cs->section_parser = section_parser;
8010
8011 LIST_ADDQ(&sections, &cs->list);
8012
8013 return 1;
8014}
8015
Willy Tarreaubaaee002006-06-26 02:48:02 +02008016/*
8017 * Local variables:
8018 * c-indent-level: 8
8019 * c-basic-offset: 8
8020 * End:
8021 */