blob: f2dc83964c58d26cb7d3a35b31dfb1d5f1d722ab [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) {
4801 if (!*(args[cur_arg + 1])) {
4802 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4803 file, linenum, args[0], args[1], ptr_arg);
4804 err_code |= ERR_ALERT | ERR_FATAL;
4805 goto out;
4806 }
4807 struct tcpcheck_rule *tcpcheck;
4808 char *err = NULL;
4809
4810 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4811
4812 tcpcheck->action = TCPCHK_ACT_EXPECT;
4813 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4814 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4815 file, linenum, args[0], args[1], args[2], err);
4816 err_code |= ERR_ALERT | ERR_FATAL;
4817 goto out;
4818 }
4819 tcpcheck->expect_regex = NULL;
4820 tcpcheck->inverse = inverse;
4821
4822 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4823 }
4824 else if (strcmp(ptr_arg, "string") == 0) {
4825 if (!*(args[cur_arg + 1])) {
4826 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4827 file, linenum, args[0], args[1], ptr_arg);
4828 err_code |= ERR_ALERT | ERR_FATAL;
4829 goto out;
4830 }
4831 struct tcpcheck_rule *tcpcheck;
4832
4833 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4834
4835 tcpcheck->action = TCPCHK_ACT_EXPECT;
4836 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4837 tcpcheck->string = strdup(args[cur_arg + 1]);
4838 tcpcheck->expect_regex = NULL;
4839 tcpcheck->inverse = inverse;
4840
4841 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4842 }
4843 else if (strcmp(ptr_arg, "rstring") == 0) {
4844 if (!*(args[cur_arg + 1])) {
4845 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4846 file, linenum, args[0], args[1], ptr_arg);
4847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
4849 }
4850 struct tcpcheck_rule *tcpcheck;
4851
4852 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4853
4854 tcpcheck->action = TCPCHK_ACT_EXPECT;
4855 tcpcheck->string_len = 0;
4856 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004857 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4858 error = NULL;
4859 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4860 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4861 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4862 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004863 err_code |= ERR_ALERT | ERR_FATAL;
4864 goto out;
4865 }
4866 tcpcheck->inverse = inverse;
4867
4868 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4869 }
4870 else {
4871 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4872 file, linenum, args[0], args[1], ptr_arg);
4873 err_code |= ERR_ALERT | ERR_FATAL;
4874 goto out;
4875 }
4876 }
4877 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004878 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004879 err_code |= ERR_ALERT | ERR_FATAL;
4880 goto out;
4881 }
4882 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004883 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004884 if (curproxy == &defproxy) {
4885 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004886 err_code |= ERR_ALERT | ERR_FATAL;
4887 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004888 }
4889
Willy Tarreaub80c2302007-11-30 20:51:32 +01004890 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004891 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004892
4893 if (strcmp(args[1], "fail") == 0) {
4894 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004895 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004896 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4897 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004900 }
4901
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004902 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4903 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4904 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004907 }
4908 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4909 }
4910 else {
4911 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004912 err_code |= ERR_ALERT | ERR_FATAL;
4913 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004914 }
4915 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004916#ifdef TPROXY
4917 else if (!strcmp(args[0], "transparent")) {
4918 /* enable transparent proxy connections */
4919 curproxy->options |= PR_O_TRANSP;
4920 }
4921#endif
4922 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004923 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004924 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004925
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 if (*(args[1]) == 0) {
4927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004928 err_code |= ERR_ALERT | ERR_FATAL;
4929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004930 }
4931 curproxy->maxconn = atol(args[1]);
4932 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004933 else if (!strcmp(args[0], "backlog")) { /* backlog */
4934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004935 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004936
4937 if (*(args[1]) == 0) {
4938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004939 err_code |= ERR_ALERT | ERR_FATAL;
4940 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004941 }
4942 curproxy->backlog = atol(args[1]);
4943 }
Willy Tarreau86034312006-12-29 00:10:33 +01004944 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004945 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004947
Willy Tarreau86034312006-12-29 00:10:33 +01004948 if (*(args[1]) == 0) {
4949 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004950 err_code |= ERR_ALERT | ERR_FATAL;
4951 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004952 }
4953 curproxy->fullconn = atol(args[1]);
4954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4956 if (*(args[1]) == 0) {
4957 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004958 err_code |= ERR_ALERT | ERR_FATAL;
4959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004961 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4962 if (err) {
4963 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4964 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004965 err_code |= ERR_ALERT | ERR_FATAL;
4966 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004967 }
4968 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004969 }
4970 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004971 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004972 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004973 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004974
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 if (curproxy == &defproxy) {
4976 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004977 err_code |= ERR_ALERT | ERR_FATAL;
4978 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004979 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004980 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004981 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004982
Willy Tarreau902636f2013-03-10 19:44:48 +01004983 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004984 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004985 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004986 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004987 goto out;
4988 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004989
4990 proto = protocol_by_family(sk->ss_family);
4991 if (!proto || !proto->connect) {
4992 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4993 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
4997
4998 if (port1 != port2) {
4999 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5000 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005001 err_code |= ERR_ALERT | ERR_FATAL;
5002 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005003 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005004
5005 if (!port1) {
5006 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5007 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005008 err_code |= ERR_ALERT | ERR_FATAL;
5009 goto out;
5010 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005011
Willy Tarreaud5191e72010-02-09 20:50:45 +01005012 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005013 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005014 }
5015 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005016 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005018
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005019 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5020 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005021 err_code |= ERR_ALERT | ERR_FATAL;
5022 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005023 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005024 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005025 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005026 /**
5027 * The syntax for hash-type config element is
5028 * hash-type {map-based|consistent} [[<algo>] avalanche]
5029 *
5030 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5031 */
5032 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005033
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005034 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5035 err_code |= ERR_WARN;
5036
5037 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005038 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5039 }
5040 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005041 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5042 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005043 else if (strcmp(args[1], "avalanche") == 0) {
5044 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]);
5045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005047 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005048 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005049 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005050 err_code |= ERR_ALERT | ERR_FATAL;
5051 goto out;
5052 }
Bhaskar98634f02013-10-29 23:30:51 -04005053
5054 /* set the hash function to use */
5055 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005056 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005057 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005058
5059 /* if consistent with no argument, then avalanche modifier is also applied */
5060 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5061 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005062 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005063 /* set the hash function */
5064 if (!strcmp(args[2], "sdbm")) {
5065 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5066 }
5067 else if (!strcmp(args[2], "djb2")) {
5068 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005069 }
5070 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005071 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005072 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005073 else if (!strcmp(args[2], "crc32")) {
5074 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5075 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005076 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005077 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 -05005078 err_code |= ERR_ALERT | ERR_FATAL;
5079 goto out;
5080 }
5081
5082 /* set the hash modifier */
5083 if (!strcmp(args[3], "avalanche")) {
5084 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5085 }
5086 else if (*args[3]) {
5087 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
5090 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005091 }
William Lallemanda73203e2012-03-12 12:48:57 +01005092 }
William Lallemanda73203e2012-03-12 12:48:57 +01005093 else if (strcmp(args[0], "unique-id-format") == 0) {
5094 if (!*(args[1])) {
5095 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
5098 }
William Lallemand3203ff42012-11-11 17:30:56 +01005099 if (*(args[2])) {
5100 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
5103 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005104 free(curproxy->conf.uniqueid_format_string);
5105 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005106
Willy Tarreau62a61232013-04-12 18:13:46 +02005107 free(curproxy->conf.uif_file);
5108 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5109 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005110 }
William Lallemanda73203e2012-03-12 12:48:57 +01005111
5112 else if (strcmp(args[0], "unique-id-header") == 0) {
5113 if (!*(args[1])) {
5114 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5115 err_code |= ERR_ALERT | ERR_FATAL;
5116 goto out;
5117 }
5118 free(curproxy->header_unique_id);
5119 curproxy->header_unique_id = strdup(args[1]);
5120 }
5121
William Lallemand723b73a2012-02-08 16:37:49 +01005122 else if (strcmp(args[0], "log-format") == 0) {
5123 if (!*(args[1])) {
5124 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
5127 }
William Lallemand3203ff42012-11-11 17:30:56 +01005128 if (*(args[2])) {
5129 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
5132 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005133
Willy Tarreau62a61232013-04-12 18:13:46 +02005134 if (curproxy->conf.logformat_string != default_http_log_format &&
5135 curproxy->conf.logformat_string != default_tcp_log_format &&
5136 curproxy->conf.logformat_string != clf_http_log_format)
5137 free(curproxy->conf.logformat_string);
5138 curproxy->conf.logformat_string = strdup(args[1]);
5139
5140 free(curproxy->conf.lfs_file);
5141 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5142 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005143
5144 /* get a chance to improve log-format error reporting by
5145 * reporting the correct line-number when possible.
5146 */
5147 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5148 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5149 file, linenum, curproxy->id);
5150 err_code |= ERR_WARN;
5151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005152 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005153 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5154 if (*(args[1]) == 0) {
5155 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5156 err_code |= ERR_ALERT | ERR_FATAL;
5157 goto out;
5158 }
5159 free(curproxy->log_tag);
5160 curproxy->log_tag = strdup(args[1]);
5161 }
William Lallemand0f99e342011-10-12 17:50:54 +02005162 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5163 /* delete previous herited or defined syslog servers */
5164 struct logsrv *back;
5165
5166 if (*(args[1]) != 0) {
5167 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5168 err_code |= ERR_ALERT | ERR_FATAL;
5169 goto out;
5170 }
5171
William Lallemand723b73a2012-02-08 16:37:49 +01005172 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5173 LIST_DEL(&tmplogsrv->list);
5174 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005175 }
5176 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005177 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005178 struct logsrv *logsrv;
5179
Willy Tarreaubaaee002006-06-26 02:48:02 +02005180 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005181 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005182 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005183 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005184 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005185 LIST_INIT(&node->list);
5186 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005188 }
5189 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005190 struct sockaddr_storage *sk;
5191 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005192 int arg = 0;
5193 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005194
5195 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005196
Willy Tarreau18324f52014-06-27 18:10:07 +02005197 /* just after the address, a length may be specified */
5198 if (strcmp(args[arg+2], "len") == 0) {
5199 len = atoi(args[arg+3]);
5200 if (len < 80 || len > 65535) {
5201 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5202 file, linenum, args[arg+3]);
5203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206 logsrv->maxlen = len;
5207
5208 /* skip these two args */
5209 arg += 2;
5210 }
5211 else
5212 logsrv->maxlen = MAX_SYSLOG_LEN;
5213
5214 if (logsrv->maxlen > global.max_syslog_len) {
5215 global.max_syslog_len = logsrv->maxlen;
5216 logline = realloc(logline, global.max_syslog_len + 1);
5217 }
5218
5219 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005220 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005221 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005222 err_code |= ERR_ALERT | ERR_FATAL;
5223 goto out;
5224
Willy Tarreaubaaee002006-06-26 02:48:02 +02005225 }
5226
William Lallemand0f99e342011-10-12 17:50:54 +02005227 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005228 if (*(args[arg+3])) {
5229 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005230 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005231 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005232 err_code |= ERR_ALERT | ERR_FATAL;
5233 goto out;
5234
Willy Tarreaubaaee002006-06-26 02:48:02 +02005235 }
5236 }
5237
William Lallemand0f99e342011-10-12 17:50:54 +02005238 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005239 if (*(args[arg+4])) {
5240 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005241 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005242 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005243 err_code |= ERR_ALERT | ERR_FATAL;
5244 goto out;
5245
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005246 }
5247 }
5248
Willy Tarreau902636f2013-03-10 19:44:48 +01005249 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005250 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005251 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005252 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005253 goto out;
5254 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005255
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005256 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005257
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005258 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005259 if (port1 != port2) {
5260 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5261 file, linenum, args[0], args[1]);
5262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
5264 }
5265
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005266 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005267 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005268 }
William Lallemand0f99e342011-10-12 17:50:54 +02005269
5270 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005271 }
5272 else {
5273 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5274 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005275 err_code |= ERR_ALERT | ERR_FATAL;
5276 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005277 }
5278 }
5279 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005280 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005281 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005282 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005283 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005284
Willy Tarreau977b8e42006-12-29 14:19:17 +01005285 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005287
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005289 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5290 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005293 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005294
5295 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005296 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5297 free(curproxy->conn_src.iface_name);
5298 curproxy->conn_src.iface_name = NULL;
5299 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005300
Willy Tarreau902636f2013-03-10 19:44:48 +01005301 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005302 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005303 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005304 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005305 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005306 goto out;
5307 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005308
5309 proto = protocol_by_family(sk->ss_family);
5310 if (!proto || !proto->connect) {
5311 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005312 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
5315 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005316
5317 if (port1 != port2) {
5318 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5319 file, linenum, args[0], args[1]);
5320 err_code |= ERR_ALERT | ERR_FATAL;
5321 goto out;
5322 }
5323
Willy Tarreauef9a3602012-12-08 22:29:20 +01005324 curproxy->conn_src.source_addr = *sk;
5325 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005326
5327 cur_arg = 2;
5328 while (*(args[cur_arg])) {
5329 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005330#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5331#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005332 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005333 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5334 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005337 }
5338#endif
5339 if (!*args[cur_arg + 1]) {
5340 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5341 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005344 }
5345
5346 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005347 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5348 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005349 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005350 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5351 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005352 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5353 char *name, *end;
5354
5355 name = args[cur_arg+1] + 7;
5356 while (isspace(*name))
5357 name++;
5358
5359 end = name;
5360 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5361 end++;
5362
Willy Tarreauef9a3602012-12-08 22:29:20 +01005363 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5364 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5365 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5366 curproxy->conn_src.bind_hdr_len = end - name;
5367 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5368 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5369 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005370
5371 /* now look for an occurrence number */
5372 while (isspace(*end))
5373 end++;
5374 if (*end == ',') {
5375 end++;
5376 name = end;
5377 if (*end == '-')
5378 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005379 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005380 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005381 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005382 }
5383
Willy Tarreauef9a3602012-12-08 22:29:20 +01005384 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005385 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5386 " occurrences values smaller than %d.\n",
5387 file, linenum, MAX_HDR_HISTORY);
5388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
5390 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005391 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005392 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005393
Willy Tarreau902636f2013-03-10 19:44:48 +01005394 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005395 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005396 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005397 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005398 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005399 goto out;
5400 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005401
5402 proto = protocol_by_family(sk->ss_family);
5403 if (!proto || !proto->connect) {
5404 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5405 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005409
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005410 if (port1 != port2) {
5411 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5412 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
5415 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005416 curproxy->conn_src.tproxy_addr = *sk;
5417 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005418 }
5419 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005420#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005421 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005422#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005423#else /* no TPROXY support */
5424 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005425 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005426 err_code |= ERR_ALERT | ERR_FATAL;
5427 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005428#endif
5429 cur_arg += 2;
5430 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005431 }
5432
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005433 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5434#ifdef SO_BINDTODEVICE
5435 if (!*args[cur_arg + 1]) {
5436 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5437 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005438 err_code |= ERR_ALERT | ERR_FATAL;
5439 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005440 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005441 free(curproxy->conn_src.iface_name);
5442 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5443 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005444 global.last_checks |= LSTCHK_NETADM;
5445#else
5446 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5447 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005450#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005451 cur_arg += 2;
5452 continue;
5453 }
5454 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005455 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005456 err_code |= ERR_ALERT | ERR_FATAL;
5457 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005458 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005459 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005460 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5461 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5462 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005463 err_code |= ERR_ALERT | ERR_FATAL;
5464 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005465 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005466 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005467 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5469 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005470 err_code |= ERR_ALERT | ERR_FATAL;
5471 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005472 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005473
5474 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005475 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005476 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005477 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005478 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005479 }
5480 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005481 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005482 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005483 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005484 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005486 }
5487 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005488 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005489 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005490 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005491 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005492 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005493 }
5494 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005495 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005496 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005497 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005498 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005500 }
5501 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005502 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005503 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005504 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005505 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005506 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005507 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005508 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005509 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005510 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005511 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005512 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005513 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005514 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005515 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005516 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005517 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005518 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005519 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005520 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005521
5522 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5523 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 +01005524 }
5525 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005526 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005527 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005528 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005529 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005530 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005531
5532 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5533 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 +01005534 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005535 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005536 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5538 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005539 err_code |= ERR_ALERT | ERR_FATAL;
5540 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005541 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005542
5543 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005544 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005545 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005546 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 }
5549 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005550 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005551 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005552 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005553 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005554 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005555 }
5556 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005557 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005558 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005559 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005560 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 }
5563 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005564 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005565 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005566 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005567 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005569 }
5570 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005571 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005572 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005573 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005574 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005575 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005576 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005577 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005578 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005579 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005580 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005581 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005582 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005585 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005586
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 if (curproxy == &defproxy) {
5588 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005592 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 if (*(args[1]) == 0) {
5596 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005599 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005600
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005601 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005602 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5603 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5604 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005605 err_code |= ERR_ALERT | ERR_FATAL;
5606 goto out;
5607 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005608 err_code |= warnif_cond_conflicts(cond,
5609 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5610 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005611 }
5612 else if (*args[2]) {
5613 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5614 file, linenum, args[0], args[2]);
5615 err_code |= ERR_ALERT | ERR_FATAL;
5616 goto out;
5617 }
5618
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005619 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005620 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005621 wl->s = strdup(args[1]);
5622 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005623 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005624 }
5625 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005626 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5628 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005629 err_code |= ERR_ALERT | ERR_FATAL;
5630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005631 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005632
Willy Tarreauade5ec42010-01-28 19:33:49 +01005633 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005634 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005635 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005636 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005637 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005638 }
5639 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005640 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005641 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005642 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005643 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005644 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005645 }
5646 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005647 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005648 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005649 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005650 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005651 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005652 }
5653 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005654 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5656 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005659 }
5660
Willy Tarreauade5ec42010-01-28 19:33:49 +01005661 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005662 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005663 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005664 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005666 }
5667 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005668 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005669 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005670 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005671 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005672 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005673 }
5674 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005675 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005676 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005677 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005678 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005679 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 }
5681 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005682 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005683
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 if (curproxy == &defproxy) {
5685 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005689 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005690 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692 if (*(args[1]) == 0) {
5693 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005694 err_code |= ERR_ALERT | ERR_FATAL;
5695 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005696 }
5697
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005698 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005699 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5700 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5701 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
5704 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005705 err_code |= warnif_cond_conflicts(cond,
5706 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5707 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005708 }
5709 else if (*args[2]) {
5710 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5711 file, linenum, args[0], args[2]);
5712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
5714 }
5715
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005716 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005717 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005718 wl->s = strdup(args[1]);
5719 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
5721 else if (!strcmp(args[0], "errorloc") ||
5722 !strcmp(args[0], "errorloc302") ||
5723 !strcmp(args[0], "errorloc303")) { /* error location */
5724 int errnum, errlen;
5725 char *err;
5726
Willy Tarreau977b8e42006-12-29 14:19:17 +01005727 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005728 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005729
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005731 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005732 err_code |= ERR_ALERT | ERR_FATAL;
5733 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005734 }
5735
5736 errnum = atol(args[1]);
5737 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005738 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5739 err = malloc(errlen);
5740 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005742 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5743 err = malloc(errlen);
5744 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 }
5746
Willy Tarreau0f772532006-12-23 20:51:41 +01005747 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5748 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005749 chunk_destroy(&curproxy->errmsg[rc]);
5750 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005751 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005754
5755 if (rc >= HTTP_ERR_SIZE) {
5756 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5757 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005758 free(err);
5759 }
5760 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005761 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5762 int errnum, errlen, fd;
5763 char *err;
5764 struct stat stat;
5765
5766 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005768
5769 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005770 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005773 }
5774
5775 fd = open(args[2], O_RDONLY);
5776 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5777 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5778 file, linenum, args[2], args[1]);
5779 if (fd >= 0)
5780 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005781 err_code |= ERR_ALERT | ERR_FATAL;
5782 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005783 }
5784
Willy Tarreau27a674e2009-08-17 07:23:33 +02005785 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005786 errlen = stat.st_size;
5787 } else {
5788 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005789 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005791 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005792 }
5793
5794 err = malloc(errlen); /* malloc() must succeed during parsing */
5795 errnum = read(fd, err, errlen);
5796 if (errnum != errlen) {
5797 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5798 file, linenum, args[2], args[1]);
5799 close(fd);
5800 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005801 err_code |= ERR_ALERT | ERR_FATAL;
5802 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005803 }
5804 close(fd);
5805
5806 errnum = atol(args[1]);
5807 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5808 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005809 chunk_destroy(&curproxy->errmsg[rc]);
5810 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005811 break;
5812 }
5813 }
5814
5815 if (rc >= HTTP_ERR_SIZE) {
5816 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5817 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005818 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005819 free(err);
5820 }
5821 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005822 else if (!strcmp(args[0], "compression")) {
5823 struct comp *comp;
5824 if (curproxy->comp == NULL) {
5825 comp = calloc(1, sizeof(struct comp));
5826 curproxy->comp = comp;
5827 } else {
5828 comp = curproxy->comp;
5829 }
5830
5831 if (!strcmp(args[1], "algo")) {
5832 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005833 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005834
William Lallemand82fe75c2012-10-23 10:25:10 +02005835 cur_arg = 2;
5836 if (!*args[cur_arg]) {
5837 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5838 file, linenum, args[0]);
5839 err_code |= ERR_ALERT | ERR_FATAL;
5840 goto out;
5841 }
5842 while (*(args[cur_arg])) {
5843 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5844 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5845 file, linenum, args[0], args[cur_arg]);
5846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
5848 }
William Lallemand552df672012-11-07 13:21:47 +01005849 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5850 curproxy->comp->algos->end(&ctx);
5851 } else {
5852 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5853 file, linenum, args[0], args[cur_arg]);
5854 err_code |= ERR_ALERT | ERR_FATAL;
5855 goto out;
5856 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005857 cur_arg ++;
5858 continue;
5859 }
5860 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005861 else if (!strcmp(args[1], "offload")) {
5862 comp->offload = 1;
5863 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005864 else if (!strcmp(args[1], "type")) {
5865 int cur_arg;
5866 cur_arg = 2;
5867 if (!*args[cur_arg]) {
5868 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5869 file, linenum, args[0]);
5870 err_code |= ERR_ALERT | ERR_FATAL;
5871 goto out;
5872 }
5873 while (*(args[cur_arg])) {
5874 comp_append_type(comp, args[cur_arg]);
5875 cur_arg ++;
5876 continue;
5877 }
5878 }
5879 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005880 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005881 file, linenum, args[0]);
5882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
5884 }
5885 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005886 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005887 struct cfg_kw_list *kwl;
5888 int index;
5889
5890 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5891 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5892 if (kwl->kw[index].section != CFG_LISTEN)
5893 continue;
5894 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5895 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005896 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005897 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005898 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005901 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005902 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005903 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005904 err_code |= ERR_WARN;
5905 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005906 }
Willy Tarreau93893792009-07-23 13:19:11 +02005907 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005908 }
5909 }
5910 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005911
Willy Tarreau6daf3432008-01-22 16:44:08 +01005912 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005913 err_code |= ERR_ALERT | ERR_FATAL;
5914 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 }
Willy Tarreau93893792009-07-23 13:19:11 +02005916 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005917 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005918 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919}
5920
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005921int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005922cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5923{
5924#ifdef CONFIG_HAP_NS
5925 const char *err;
5926 const char *item = args[0];
5927
5928 if (!strcmp(item, "namespace_list")) {
5929 return 0;
5930 }
5931 else if (!strcmp(item, "namespace")) {
5932 size_t idx = 1;
5933 const char *current;
5934 while (*(current = args[idx++])) {
5935 err = invalid_char(current);
5936 if (err) {
5937 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5938 file, linenum, *err, item, current);
5939 return ERR_ALERT | ERR_FATAL;
5940 }
5941
5942 if (netns_store_lookup(current, strlen(current))) {
5943 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5944 file, linenum, current);
5945 return ERR_ALERT | ERR_FATAL;
5946 }
5947 if (!netns_store_insert(current)) {
5948 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5949 file, linenum, current);
5950 return ERR_ALERT | ERR_FATAL;
5951 }
5952 }
5953 }
5954
5955 return 0;
5956#else
5957 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5958 file, linenum);
5959 return ERR_ALERT | ERR_FATAL;
5960#endif
5961}
5962
5963int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005964cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5965{
5966
5967 int err_code = 0;
5968 const char *err;
5969
5970 if (!strcmp(args[0], "userlist")) { /* new userlist */
5971 struct userlist *newul;
5972
5973 if (!*args[1]) {
5974 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5975 file, linenum, args[0]);
5976 err_code |= ERR_ALERT | ERR_FATAL;
5977 goto out;
5978 }
5979
5980 err = invalid_char(args[1]);
5981 if (err) {
5982 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5983 file, linenum, *err, args[0], args[1]);
5984 err_code |= ERR_ALERT | ERR_FATAL;
5985 goto out;
5986 }
5987
5988 for (newul = userlist; newul; newul = newul->next)
5989 if (!strcmp(newul->name, args[1])) {
5990 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5991 file, linenum, args[1]);
5992 err_code |= ERR_WARN;
5993 goto out;
5994 }
5995
5996 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5997 if (!newul) {
5998 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5999 err_code |= ERR_ALERT | ERR_ABORT;
6000 goto out;
6001 }
6002
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006003 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006004 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006005 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6006 err_code |= ERR_ALERT | ERR_ABORT;
6007 goto out;
6008 }
6009
6010 newul->next = userlist;
6011 userlist = newul;
6012
6013 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006014 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006015 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006016 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006017
6018 if (!*args[1]) {
6019 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6020 file, linenum, args[0]);
6021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
6023 }
6024
6025 err = invalid_char(args[1]);
6026 if (err) {
6027 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6028 file, linenum, *err, args[0], args[1]);
6029 err_code |= ERR_ALERT | ERR_FATAL;
6030 goto out;
6031 }
6032
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006033 for (ag = userlist->groups; ag; ag = ag->next)
6034 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006035 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6036 file, linenum, args[1], userlist->name);
6037 err_code |= ERR_ALERT;
6038 goto out;
6039 }
6040
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006041 ag = calloc(1, sizeof(*ag));
6042 if (!ag) {
6043 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6044 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006045 goto out;
6046 }
6047
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006048 ag->name = strdup(args[1]);
6049 if (!ag) {
6050 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6051 err_code |= ERR_ALERT | ERR_ABORT;
6052 goto out;
6053 }
6054
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006055 cur_arg = 2;
6056
6057 while (*args[cur_arg]) {
6058 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006059 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006060 cur_arg += 2;
6061 continue;
6062 } else {
6063 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6064 file, linenum, args[0]);
6065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
6067 }
6068 }
6069
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006070 ag->next = userlist->groups;
6071 userlist->groups = ag;
6072
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006073 } else if (!strcmp(args[0], "user")) { /* new user */
6074 struct auth_users *newuser;
6075 int cur_arg;
6076
6077 if (!*args[1]) {
6078 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6079 file, linenum, args[0]);
6080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
6082 }
6083
6084 for (newuser = userlist->users; newuser; newuser = newuser->next)
6085 if (!strcmp(newuser->user, args[1])) {
6086 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6087 file, linenum, args[1], userlist->name);
6088 err_code |= ERR_ALERT;
6089 goto out;
6090 }
6091
6092 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6093 if (!newuser) {
6094 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6095 err_code |= ERR_ALERT | ERR_ABORT;
6096 goto out;
6097 }
6098
6099 newuser->user = strdup(args[1]);
6100
6101 newuser->next = userlist->users;
6102 userlist->users = newuser;
6103
6104 cur_arg = 2;
6105
6106 while (*args[cur_arg]) {
6107 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006108#ifdef CONFIG_HAP_CRYPT
6109 if (!crypt("", args[cur_arg + 1])) {
6110 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6111 file, linenum, newuser->user);
6112 err_code |= ERR_ALERT | ERR_FATAL;
6113 goto out;
6114 }
6115#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006116 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6117 file, linenum);
6118 err_code |= ERR_ALERT;
6119#endif
6120 newuser->pass = strdup(args[cur_arg + 1]);
6121 cur_arg += 2;
6122 continue;
6123 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6124 newuser->pass = strdup(args[cur_arg + 1]);
6125 newuser->flags |= AU_O_INSECURE;
6126 cur_arg += 2;
6127 continue;
6128 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006129 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006130 cur_arg += 2;
6131 continue;
6132 } else {
6133 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6134 file, linenum, args[0]);
6135 err_code |= ERR_ALERT | ERR_FATAL;
6136 goto out;
6137 }
6138 }
6139 } else {
6140 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6141 err_code |= ERR_ALERT | ERR_FATAL;
6142 }
6143
6144out:
6145 return err_code;
6146}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006147
6148/*
6149 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006150 * Returns the error code, 0 if OK, or any combination of :
6151 * - ERR_ABORT: must abort ASAP
6152 * - ERR_FATAL: we can continue parsing but not start the service
6153 * - ERR_WARN: a warning has been emitted
6154 * - ERR_ALERT: an alert has been emitted
6155 * Only the two first ones can stop processing, the two others are just
6156 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006158int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006160 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006161 FILE *f;
6162 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006163 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006164 struct cfg_section *cs = NULL;
6165 struct cfg_section *ics;
6166
6167 /* Register internal sections */
6168 if (!cfg_register_section("listen", cfg_parse_listen) ||
6169 !cfg_register_section("frontend", cfg_parse_listen) ||
6170 !cfg_register_section("backend", cfg_parse_listen) ||
6171 !cfg_register_section("ruleset", cfg_parse_listen) ||
6172 !cfg_register_section("defaults", cfg_parse_listen) ||
6173 !cfg_register_section("global", cfg_parse_global) ||
6174 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006175 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006176 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006177 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006178 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179
Willy Tarreaubaaee002006-06-26 02:48:02 +02006180 if ((f=fopen(file,"r")) == NULL)
6181 return -1;
6182
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006183 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006184 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006185 char *end;
6186 char *args[MAX_LINE_ARGS + 1];
6187 char *line = thisline;
6188
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189 linenum++;
6190
6191 end = line + strlen(line);
6192
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006193 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6194 /* Check if we reached the limit and the last char is not \n.
6195 * Watch out for the last line without the terminating '\n'!
6196 */
6197 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006198 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006199 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006200 }
6201
Willy Tarreaubaaee002006-06-26 02:48:02 +02006202 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006203 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 line++;
6205
6206 arg = 0;
6207 args[arg] = line;
6208
6209 while (*line && arg < MAX_LINE_ARGS) {
6210 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6211 * C equivalent value. Other combinations left unchanged (eg: \1).
6212 */
6213 if (*line == '\\') {
6214 int skip = 0;
6215 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6216 *line = line[1];
6217 skip = 1;
6218 }
6219 else if (line[1] == 'r') {
6220 *line = '\r';
6221 skip = 1;
6222 }
6223 else if (line[1] == 'n') {
6224 *line = '\n';
6225 skip = 1;
6226 }
6227 else if (line[1] == 't') {
6228 *line = '\t';
6229 skip = 1;
6230 }
6231 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006232 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006233 unsigned char hex1, hex2;
6234 hex1 = toupper(line[2]) - '0';
6235 hex2 = toupper(line[3]) - '0';
6236 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6237 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6238 *line = (hex1<<4) + hex2;
6239 skip = 3;
6240 }
6241 else {
6242 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006243 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 }
6245 }
6246 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006247 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006248 end -= skip;
6249 }
6250 line++;
6251 }
6252 else if (*line == '#' || *line == '\n' || *line == '\r') {
6253 /* end of string, end of loop */
6254 *line = 0;
6255 break;
6256 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006257 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006258 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006259 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006260 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006261 line++;
6262 args[++arg] = line;
6263 }
6264 else {
6265 line++;
6266 }
6267 }
6268
6269 /* empty line */
6270 if (!**args)
6271 continue;
6272
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006273 if (*line) {
6274 /* we had to stop due to too many args.
6275 * Let's terminate the string, print the offending part then cut the
6276 * last arg.
6277 */
6278 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6279 line++;
6280 *line = '\0';
6281
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006282 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006283 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006284 err_code |= ERR_ALERT | ERR_FATAL;
6285 args[arg] = line;
6286 }
6287
Willy Tarreau540abe42007-05-02 20:50:16 +02006288 /* zero out remaining args and ensure that at least one entry
6289 * is zeroed out.
6290 */
6291 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006292 args[arg] = line;
6293 }
6294
Willy Tarreau3842f002009-06-14 11:39:52 +02006295 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006296 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006297 char *tmp;
6298
Willy Tarreau3842f002009-06-14 11:39:52 +02006299 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006300 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006301 for (arg=0; *args[arg+1]; arg++)
6302 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006303 *tmp = '\0'; // fix the next arg to \0
6304 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006305 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006306 else if (!strcmp(args[0], "default")) {
6307 kwm = KWM_DEF;
6308 for (arg=0; *args[arg+1]; arg++)
6309 args[arg] = args[arg+1]; // shift args after inversion
6310 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006311
William Lallemand0f99e342011-10-12 17:50:54 +02006312 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6313 strcmp(args[0], "log") != 0) {
6314 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006315 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006316 }
6317
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006318 /* detect section start */
6319 list_for_each_entry(ics, &sections, list) {
6320 if (strcmp(args[0], ics->section_name) == 0) {
6321 cursection = ics->section_name;
6322 cs = ics;
6323 break;
6324 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006325 }
6326
Willy Tarreaubaaee002006-06-26 02:48:02 +02006327 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006328 if (cs)
6329 err_code |= cs->section_parser(file, linenum, args, kwm);
6330 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006331 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006332 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006334
6335 if (err_code & ERR_ABORT)
6336 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006338 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006339 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006340 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006341}
6342
Willy Tarreau64ab6072014-09-16 12:17:36 +02006343/* This function propagates processes from frontend <from> to backend <to> so
6344 * that it is always guaranteed that a backend pointed to by a frontend is
6345 * bound to all of its processes. After that, if the target is a "listen"
6346 * instance, the function recursively descends the target's own targets along
6347 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6348 * checked first to ensure that <to> is already bound to all processes of
6349 * <from>, there is no risk of looping and we ensure to follow the shortest
6350 * path to the destination.
6351 *
6352 * It is possible to set <to> to NULL for the first call so that the function
6353 * takes care of visiting the initial frontend in <from>.
6354 *
6355 * It is important to note that the function relies on the fact that all names
6356 * have already been resolved.
6357 */
6358void propagate_processes(struct proxy *from, struct proxy *to)
6359{
6360 struct switching_rule *rule;
6361 struct hdr_exp *exp;
6362
6363 if (to) {
6364 /* check whether we need to go down */
6365 if (from->bind_proc &&
6366 (from->bind_proc & to->bind_proc) == from->bind_proc)
6367 return;
6368
6369 if (!from->bind_proc && !to->bind_proc)
6370 return;
6371
6372 to->bind_proc = from->bind_proc ?
6373 (to->bind_proc | from->bind_proc) : 0;
6374
6375 /* now propagate down */
6376 from = to;
6377 }
6378
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006379 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006380 return;
6381
Willy Tarreauf6b70012014-12-18 14:00:43 +01006382 if (from->state == PR_STSTOPPED)
6383 return;
6384
Willy Tarreau64ab6072014-09-16 12:17:36 +02006385 /* default_backend */
6386 if (from->defbe.be)
6387 propagate_processes(from, from->defbe.be);
6388
6389 /* use_backend */
6390 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006391 if (rule->dynamic)
6392 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006393 to = rule->be.backend;
6394 propagate_processes(from, to);
6395 }
6396
6397 /* reqsetbe */
6398 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6399 if (exp->action != ACT_SETBE)
6400 continue;
6401 to = (struct proxy *)exp->replace;
6402 propagate_processes(from, to);
6403 }
6404}
6405
Willy Tarreaubb925012009-07-23 13:36:36 +02006406/*
6407 * Returns the error code, 0 if OK, or any combination of :
6408 * - ERR_ABORT: must abort ASAP
6409 * - ERR_FATAL: we can continue parsing but not start the service
6410 * - ERR_WARN: a warning has been emitted
6411 * - ERR_ALERT: an alert has been emitted
6412 * Only the two first ones can stop processing, the two others are just
6413 * indicators.
6414 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006415int check_config_validity()
6416{
6417 int cfgerr = 0;
6418 struct proxy *curproxy = NULL;
6419 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006420 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006421 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006422 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006424 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006425 /*
6426 * Now, check for the integrity of all that we have collected.
6427 */
6428
6429 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006430 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006431
Willy Tarreau193b8c62012-11-22 00:17:38 +01006432 if (!global.tune.max_http_hdr)
6433 global.tune.max_http_hdr = MAX_HTTP_HDR;
6434
6435 if (!global.tune.cookie_len)
6436 global.tune.cookie_len = CAPTURE_LEN;
6437
6438 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6439
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006440 /* Post initialisation of the users and groups lists. */
6441 err_code = userlist_postinit();
6442 if (err_code != ERR_NONE)
6443 goto out;
6444
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006445 /* first, we will invert the proxy list order */
6446 curproxy = NULL;
6447 while (proxy) {
6448 struct proxy *next;
6449
6450 next = proxy->next;
6451 proxy->next = curproxy;
6452 curproxy = proxy;
6453 if (!next)
6454 break;
6455 proxy = next;
6456 }
6457
Willy Tarreau419ead82014-09-16 13:41:21 +02006458 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006459 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006460 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006461 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006462 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006463 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006464 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006465 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006466
Willy Tarreau050536d2012-10-04 08:47:34 +02006467 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006468 /* proxy ID not set, use automatic numbering with first
6469 * spare entry starting with next_pxid.
6470 */
6471 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6472 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6473 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006474 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006475 next_pxid++;
6476
Willy Tarreau55ea7572007-06-17 19:56:27 +02006477
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006479 /* ensure we don't keep listeners uselessly bound */
6480 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 continue;
6482 }
6483
Willy Tarreau102df612014-05-07 23:56:38 +02006484 /* Check multi-process mode compatibility for the current proxy */
6485
6486 if (curproxy->bind_proc) {
6487 /* an explicit bind-process was specified, let's check how many
6488 * processes remain.
6489 */
6490 nbproc = popcount(curproxy->bind_proc);
6491
6492 curproxy->bind_proc &= nbits(global.nbproc);
6493 if (!curproxy->bind_proc && nbproc == 1) {
6494 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);
6495 curproxy->bind_proc = 1;
6496 }
6497 else if (!curproxy->bind_proc && nbproc > 1) {
6498 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);
6499 curproxy->bind_proc = 0;
6500 }
6501 }
6502
Willy Tarreau3d209582014-05-09 17:06:11 +02006503 /* check and reduce the bind-proc of each listener */
6504 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6505 unsigned long mask;
6506
6507 if (!bind_conf->bind_proc)
6508 continue;
6509
6510 mask = nbits(global.nbproc);
6511 if (curproxy->bind_proc)
6512 mask &= curproxy->bind_proc;
6513 /* mask cannot be null here thanks to the previous checks */
6514
6515 nbproc = popcount(bind_conf->bind_proc);
6516 bind_conf->bind_proc &= mask;
6517
6518 if (!bind_conf->bind_proc && nbproc == 1) {
6519 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",
6520 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6521 bind_conf->bind_proc = mask & ~(mask - 1);
6522 }
6523 else if (!bind_conf->bind_proc && nbproc > 1) {
6524 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",
6525 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6526 bind_conf->bind_proc = 0;
6527 }
6528 }
6529
Willy Tarreau102df612014-05-07 23:56:38 +02006530 if (global.nbproc > 1 && curproxy->table.peers.name) {
6531 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6532 curproxy->id);
6533 cfgerr++;
6534 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006535
Willy Tarreauff01a212009-03-15 13:46:16 +01006536 switch (curproxy->mode) {
6537 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006538 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006539 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006540 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6541 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006542 cfgerr++;
6543 }
6544
6545 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006546 Warning("config : servers will be ignored for %s '%s'.\n",
6547 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006548 break;
6549
6550 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006551 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006552 break;
6553
6554 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006555 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006556 break;
6557 }
6558
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006559 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006560 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006561 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006562 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6563 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006564 cfgerr++;
6565 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006566#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006567 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006568 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6569 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006570 cfgerr++;
6571 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006573 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006574 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6575 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006576 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006577 }
6578 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006579 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006580 /* If no LB algo is set in a backend, and we're not in
6581 * transparent mode, dispatch mode nor proxy mode, we
6582 * want to use balance roundrobin by default.
6583 */
6584 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6585 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006586 }
6587 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006588
Willy Tarreau1620ec32011-08-06 17:05:02 +02006589 if (curproxy->options & PR_O_DISPATCH)
6590 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6591 else if (curproxy->options & PR_O_HTTP_PROXY)
6592 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6593 else if (curproxy->options & PR_O_TRANSP)
6594 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006595
Willy Tarreau1620ec32011-08-06 17:05:02 +02006596 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6597 if (curproxy->options & PR_O_DISABLE404) {
6598 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6599 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6600 err_code |= ERR_WARN;
6601 curproxy->options &= ~PR_O_DISABLE404;
6602 }
6603 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6604 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6605 "send-state", proxy_type_str(curproxy), curproxy->id);
6606 err_code |= ERR_WARN;
6607 curproxy->options &= ~PR_O2_CHK_SNDST;
6608 }
Willy Tarreauef781042010-01-27 11:53:01 +01006609 }
6610
Simon Horman98637e52014-06-20 12:30:16 +09006611 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6612 if (!global.external_check) {
6613 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6614 curproxy->id, "option external-check");
6615 cfgerr++;
6616 }
6617 if (!curproxy->check_command) {
6618 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6619 curproxy->id, "option external-check");
6620 cfgerr++;
6621 }
6622 }
6623
Simon Horman64e34162015-02-06 11:11:57 +09006624 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006625 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6626 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006627 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6628 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006629 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6630 "to be present).\n",
6631 proxy_type_str(curproxy), curproxy->id);
6632 err_code |= ERR_WARN;
6633 free_email_alert(curproxy);
6634 }
6635 if (!curproxy->email_alert.myhostname)
6636 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006637 }
6638
Simon Horman98637e52014-06-20 12:30:16 +09006639 if (curproxy->check_command) {
6640 int clear = 0;
6641 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6642 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6643 "external-check command", proxy_type_str(curproxy), curproxy->id);
6644 err_code |= ERR_WARN;
6645 clear = 1;
6646 }
6647 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6648 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6649 curproxy->id, "external-check command");
6650 cfgerr++;
6651 }
6652 if (clear) {
6653 free(curproxy->check_command);
6654 curproxy->check_command = NULL;
6655 }
6656 }
6657
6658 if (curproxy->check_path) {
6659 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6660 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6661 "external-check path", proxy_type_str(curproxy), curproxy->id);
6662 err_code |= ERR_WARN;
6663 free(curproxy->check_path);
6664 curproxy->check_path = NULL;
6665 }
6666 }
6667
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006668 /* if a default backend was specified, let's find it */
6669 if (curproxy->defbe.name) {
6670 struct proxy *target;
6671
Alex Williams96532db2009-11-01 21:27:13 -05006672 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006673 if (!target) {
6674 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6675 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006676 cfgerr++;
6677 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006678 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6679 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006680 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006681 } else {
6682 free(curproxy->defbe.name);
6683 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006684
6685 /* Emit a warning if this proxy also has some servers */
6686 if (curproxy->srv) {
6687 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6688 curproxy->id);
6689 err_code |= ERR_WARN;
6690 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006691 }
6692 }
6693
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006694 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006695 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6696 /* map jump target for ACT_SETBE in req_rep chain */
6697 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006698 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006699 struct proxy *target;
6700
Willy Tarreaua496b602006-12-17 23:15:24 +01006701 if (exp->action != ACT_SETBE)
6702 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006703
Alex Williams96532db2009-11-01 21:27:13 -05006704 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006705 if (!target) {
6706 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6707 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006708 cfgerr++;
6709 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006710 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6711 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006712 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006713 } else {
6714 free((void *)exp->replace);
6715 exp->replace = (const char *)target;
6716 }
6717 }
6718 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006719
6720 /* find the target proxy for 'use_backend' rules */
6721 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006722 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006723 struct logformat_node *node;
6724 char *pxname;
6725
6726 /* Try to parse the string as a log format expression. If the result
6727 * of the parsing is only one entry containing a simple string, then
6728 * it's a standard string corresponding to a static rule, thus the
6729 * parsing is cancelled and be.name is restored to be resolved.
6730 */
6731 pxname = rule->be.name;
6732 LIST_INIT(&rule->be.expr);
6733 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6734 curproxy->conf.args.file, curproxy->conf.args.line);
6735 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6736
6737 if (!LIST_ISEMPTY(&rule->be.expr)) {
6738 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6739 rule->dynamic = 1;
6740 free(pxname);
6741 continue;
6742 }
6743 /* simple string: free the expression and fall back to static rule */
6744 free(node->arg);
6745 free(node);
6746 }
6747
6748 rule->dynamic = 0;
6749 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006750
Alex Williams96532db2009-11-01 21:27:13 -05006751 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006752
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006753 if (!target) {
6754 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6755 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006756 cfgerr++;
6757 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006758 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6759 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006760 cfgerr++;
6761 } else {
6762 free((void *)rule->be.name);
6763 rule->be.backend = target;
6764 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006765 }
6766
Willy Tarreau64ab6072014-09-16 12:17:36 +02006767 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006768 list_for_each_entry(srule, &curproxy->server_rules, list) {
6769 struct server *target = findserver(curproxy, srule->srv.name);
6770
6771 if (!target) {
6772 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6773 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6774 cfgerr++;
6775 continue;
6776 }
6777 free((void *)srule->srv.name);
6778 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006779 }
6780
Emeric Brunb982a3d2010-01-04 15:45:53 +01006781 /* find the target table for 'stick' rules */
6782 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6783 struct proxy *target;
6784
Emeric Brun1d33b292010-01-04 15:47:17 +01006785 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6786 if (mrule->flags & STK_IS_STORE)
6787 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6788
Emeric Brunb982a3d2010-01-04 15:45:53 +01006789 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006790 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006791 else
6792 target = curproxy;
6793
6794 if (!target) {
6795 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6796 curproxy->id, mrule->table.name);
6797 cfgerr++;
6798 }
6799 else if (target->table.size == 0) {
6800 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6801 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6802 cfgerr++;
6803 }
Willy Tarreau12785782012-04-27 21:37:17 +02006804 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6805 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006806 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6807 cfgerr++;
6808 }
6809 else {
6810 free((void *)mrule->table.name);
6811 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006812 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006813 }
6814 }
6815
6816 /* find the target table for 'store response' rules */
6817 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6818 struct proxy *target;
6819
Emeric Brun1d33b292010-01-04 15:47:17 +01006820 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6821
Emeric Brunb982a3d2010-01-04 15:45:53 +01006822 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006823 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006824 else
6825 target = curproxy;
6826
6827 if (!target) {
6828 Alert("Proxy '%s': unable to find store table '%s'.\n",
6829 curproxy->id, mrule->table.name);
6830 cfgerr++;
6831 }
6832 else if (target->table.size == 0) {
6833 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6834 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6835 cfgerr++;
6836 }
Willy Tarreau12785782012-04-27 21:37:17 +02006837 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6838 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006839 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6840 cfgerr++;
6841 }
6842 else {
6843 free((void *)mrule->table.name);
6844 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006845 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006846 }
6847 }
6848
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006849 /* find the target table for 'tcp-request' layer 4 rules */
6850 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6851 struct proxy *target;
6852
Willy Tarreaub4c84932013-07-23 19:15:30 +02006853 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006854 continue;
6855
6856 if (trule->act_prm.trk_ctr.table.n)
6857 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6858 else
6859 target = curproxy;
6860
6861 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006862 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6863 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006864 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006865 cfgerr++;
6866 }
6867 else if (target->table.size == 0) {
6868 Alert("Proxy '%s': table '%s' used but not configured.\n",
6869 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6870 cfgerr++;
6871 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006872 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6873 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6874 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 +01006875 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006876 cfgerr++;
6877 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006878 else {
6879 free(trule->act_prm.trk_ctr.table.n);
6880 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006881 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006882 * to pass a list of counters to track and allocate them right here using
6883 * stktable_alloc_data_type().
6884 */
6885 }
6886 }
6887
Willy Tarreaud1f96522010-08-03 19:34:32 +02006888 /* find the target table for 'tcp-request' layer 6 rules */
6889 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6890 struct proxy *target;
6891
Willy Tarreaub4c84932013-07-23 19:15:30 +02006892 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006893 continue;
6894
6895 if (trule->act_prm.trk_ctr.table.n)
6896 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6897 else
6898 target = curproxy;
6899
6900 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006901 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6902 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006903 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006904 cfgerr++;
6905 }
6906 else if (target->table.size == 0) {
6907 Alert("Proxy '%s': table '%s' used but not configured.\n",
6908 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6909 cfgerr++;
6910 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006911 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6912 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6913 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 +01006914 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006915 cfgerr++;
6916 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006917 else {
6918 free(trule->act_prm.trk_ctr.table.n);
6919 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006920 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006921 * to pass a list of counters to track and allocate them right here using
6922 * stktable_alloc_data_type().
6923 */
6924 }
6925 }
6926
Willy Tarreau09448f72014-06-25 18:12:15 +02006927 /* find the target table for 'http-request' layer 7 rules */
6928 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6929 struct proxy *target;
6930
6931 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6932 continue;
6933
6934 if (hrqrule->act_prm.trk_ctr.table.n)
6935 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6936 else
6937 target = curproxy;
6938
6939 if (!target) {
6940 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6941 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6942 http_req_trk_idx(hrqrule->action));
6943 cfgerr++;
6944 }
6945 else if (target->table.size == 0) {
6946 Alert("Proxy '%s': table '%s' used but not configured.\n",
6947 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6948 cfgerr++;
6949 }
6950 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6951 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6952 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6953 http_req_trk_idx(hrqrule->action));
6954 cfgerr++;
6955 }
6956 else {
6957 free(hrqrule->act_prm.trk_ctr.table.n);
6958 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6959 /* Note: if we decide to enhance the track-sc syntax, we may be able
6960 * to pass a list of counters to track and allocate them right here using
6961 * stktable_alloc_data_type().
6962 */
6963 }
6964 }
6965
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006966 /* move any "block" rules at the beginning of the http-request rules */
6967 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6968 /* insert block_rules into http_req_rules at the beginning */
6969 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6970 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6971 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6972 curproxy->http_req_rules.n = curproxy->block_rules.n;
6973 LIST_INIT(&curproxy->block_rules);
6974 }
6975
Emeric Brun32da3c42010-09-23 18:39:19 +02006976 if (curproxy->table.peers.name) {
6977 struct peers *curpeers = peers;
6978
6979 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6980 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6981 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006982 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006983 break;
6984 }
6985 }
6986
6987 if (!curpeers) {
6988 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6989 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006990 free((void *)curproxy->table.peers.name);
6991 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006992 cfgerr++;
6993 }
6994 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006995 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6996 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006997 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006998 cfgerr++;
6999 }
7000 }
7001
Simon Horman9dc49962015-01-30 11:22:59 +09007002
7003 if (curproxy->email_alert.mailers.name) {
7004 struct mailers *curmailers = mailers;
7005
7006 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7007 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7008 free(curproxy->email_alert.mailers.name);
7009 curproxy->email_alert.mailers.m = curmailers;
7010 curmailers->users++;
7011 break;
7012 }
7013 }
7014
7015 if (!curmailers) {
7016 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7017 curproxy->id, curproxy->email_alert.mailers.name);
7018 free_email_alert(curproxy);
7019 cfgerr++;
7020 }
7021 }
7022
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007023 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007024 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007025 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7026 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7027 "proxy", curproxy->id);
7028 cfgerr++;
7029 goto out_uri_auth_compat;
7030 }
7031
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007032 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007033 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007034 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007035 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007036
Willy Tarreau95fa4692010-02-01 13:05:50 +01007037 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7038 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007039
7040 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007041 uri_auth_compat_req[i++] = "realm";
7042 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7043 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007044
Willy Tarreau95fa4692010-02-01 13:05:50 +01007045 uri_auth_compat_req[i++] = "unless";
7046 uri_auth_compat_req[i++] = "{";
7047 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7048 uri_auth_compat_req[i++] = "}";
7049 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007050
Willy Tarreauff011f22011-01-06 17:51:27 +01007051 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7052 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007053 cfgerr++;
7054 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007055 }
7056
Willy Tarreauff011f22011-01-06 17:51:27 +01007057 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007058
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007059 if (curproxy->uri_auth->auth_realm) {
7060 free(curproxy->uri_auth->auth_realm);
7061 curproxy->uri_auth->auth_realm = NULL;
7062 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007063
7064 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007065 }
7066out_uri_auth_compat:
7067
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007068 /* compile the log format */
7069 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007070 if (curproxy->conf.logformat_string != default_http_log_format &&
7071 curproxy->conf.logformat_string != default_tcp_log_format &&
7072 curproxy->conf.logformat_string != clf_http_log_format)
7073 free(curproxy->conf.logformat_string);
7074 curproxy->conf.logformat_string = NULL;
7075 free(curproxy->conf.lfs_file);
7076 curproxy->conf.lfs_file = NULL;
7077 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007078 }
7079
Willy Tarreau62a61232013-04-12 18:13:46 +02007080 if (curproxy->conf.logformat_string) {
7081 curproxy->conf.args.ctx = ARGC_LOG;
7082 curproxy->conf.args.file = curproxy->conf.lfs_file;
7083 curproxy->conf.args.line = curproxy->conf.lfs_line;
7084 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007085 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007086 curproxy->conf.args.file = NULL;
7087 curproxy->conf.args.line = 0;
7088 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007089
Willy Tarreau62a61232013-04-12 18:13:46 +02007090 if (curproxy->conf.uniqueid_format_string) {
7091 curproxy->conf.args.ctx = ARGC_UIF;
7092 curproxy->conf.args.file = curproxy->conf.uif_file;
7093 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007094 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007095 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007096 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007097 curproxy->conf.args.file = NULL;
7098 curproxy->conf.args.line = 0;
7099 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007100
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007101 /* only now we can check if some args remain unresolved.
7102 * This must be done after the users and groups resolution.
7103 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007104 cfgerr += smp_resolve_args(curproxy);
7105 if (!cfgerr)
7106 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007107
Willy Tarreau2738a142006-07-08 17:28:09 +02007108 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007109 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007110 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007111 (!curproxy->timeout.connect ||
7112 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007113 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007114 " | While not properly invalid, you will certainly encounter various problems\n"
7115 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007116 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007117 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007118 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007119 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007120
Willy Tarreau1fa31262007-12-03 00:36:16 +01007121 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7122 * We must still support older configurations, so let's find out whether those
7123 * parameters have been set or must be copied from contimeouts.
7124 */
7125 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007126 if (!curproxy->timeout.tarpit ||
7127 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007128 /* tarpit timeout not set. We search in the following order:
7129 * default.tarpit, curr.connect, default.connect.
7130 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007131 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007132 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007133 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007134 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007135 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007136 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007137 }
7138 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007139 (!curproxy->timeout.queue ||
7140 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007141 /* queue timeout not set. We search in the following order:
7142 * default.queue, curr.connect, default.connect.
7143 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007144 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007145 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007146 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007147 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007148 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007149 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007150 }
7151 }
7152
Willy Tarreau1620ec32011-08-06 17:05:02 +02007153 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007154 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7155 curproxy->check_req = (char *)malloc(curproxy->check_len);
7156 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007157 }
7158
Willy Tarreau215663d2014-06-13 18:30:23 +02007159 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7160 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7161 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7162 proxy_type_str(curproxy), curproxy->id);
7163 err_code |= ERR_WARN;
7164 }
7165
Willy Tarreau193b8c62012-11-22 00:17:38 +01007166 /* ensure that cookie capture length is not too large */
7167 if (curproxy->capture_len >= global.tune.cookie_len) {
7168 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7169 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7170 err_code |= ERR_WARN;
7171 curproxy->capture_len = global.tune.cookie_len - 1;
7172 }
7173
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007174 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007175 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007176 curproxy->req_cap_pool = create_pool("ptrcap",
7177 curproxy->nb_req_cap * sizeof(char *),
7178 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007179 }
7180
7181 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007182 curproxy->rsp_cap_pool = create_pool("ptrcap",
7183 curproxy->nb_rsp_cap * sizeof(char *),
7184 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007185 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007186
Willy Tarreaubaaee002006-06-26 02:48:02 +02007187 /* first, we will invert the servers list order */
7188 newsrv = NULL;
7189 while (curproxy->srv) {
7190 struct server *next;
7191
7192 next = curproxy->srv->next;
7193 curproxy->srv->next = newsrv;
7194 newsrv = curproxy->srv;
7195 if (!next)
7196 break;
7197 curproxy->srv = next;
7198 }
7199
Willy Tarreau17edc812014-01-03 12:14:34 +01007200 /* Check that no server name conflicts. This causes trouble in the stats.
7201 * We only emit a warning for the first conflict affecting each server,
7202 * in order to avoid combinatory explosion if all servers have the same
7203 * name. We do that only for servers which do not have an explicit ID,
7204 * because these IDs were made also for distinguishing them and we don't
7205 * want to annoy people who correctly manage them.
7206 */
7207 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7208 struct server *other_srv;
7209
7210 if (newsrv->puid)
7211 continue;
7212
7213 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7214 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7215 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7216 newsrv->conf.file, newsrv->conf.line,
7217 proxy_type_str(curproxy), curproxy->id,
7218 newsrv->id, other_srv->conf.line);
7219 break;
7220 }
7221 }
7222 }
7223
Willy Tarreaudd701652010-05-25 23:03:02 +02007224 /* assign automatic UIDs to servers which don't have one yet */
7225 next_id = 1;
7226 newsrv = curproxy->srv;
7227 while (newsrv != NULL) {
7228 if (!newsrv->puid) {
7229 /* server ID not set, use automatic numbering with first
7230 * spare entry starting with next_svid.
7231 */
7232 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7233 newsrv->conf.id.key = newsrv->puid = next_id;
7234 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7235 }
7236 next_id++;
7237 newsrv = newsrv->next;
7238 }
7239
Willy Tarreau20697042007-11-15 23:26:18 +01007240 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007241 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007242
Willy Tarreau62c3be22012-01-20 13:12:32 +01007243 /*
7244 * If this server supports a maxconn parameter, it needs a dedicated
7245 * tasks to fill the emptied slots when a connection leaves.
7246 * Also, resolve deferred tracking dependency if needed.
7247 */
7248 newsrv = curproxy->srv;
7249 while (newsrv != NULL) {
7250 if (newsrv->minconn > newsrv->maxconn) {
7251 /* Only 'minconn' was specified, or it was higher than or equal
7252 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7253 * this will avoid further useless expensive computations.
7254 */
7255 newsrv->maxconn = newsrv->minconn;
7256 } else if (newsrv->maxconn && !newsrv->minconn) {
7257 /* minconn was not specified, so we set it to maxconn */
7258 newsrv->minconn = newsrv->maxconn;
7259 }
7260
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007261#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007262 if (newsrv->use_ssl || newsrv->check.use_ssl)
7263 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007264#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007265
Willy Tarreau2f075e92013-12-03 11:11:34 +01007266 /* set the check type on the server */
7267 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7268
Willy Tarreau62c3be22012-01-20 13:12:32 +01007269 if (newsrv->trackit) {
7270 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007271 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007272 char *pname, *sname;
7273
7274 pname = newsrv->trackit;
7275 sname = strrchr(pname, '/');
7276
7277 if (sname)
7278 *sname++ = '\0';
7279 else {
7280 sname = pname;
7281 pname = NULL;
7282 }
7283
7284 if (pname) {
7285 px = findproxy(pname, PR_CAP_BE);
7286 if (!px) {
7287 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7288 proxy_type_str(curproxy), curproxy->id,
7289 newsrv->id, pname);
7290 cfgerr++;
7291 goto next_srv;
7292 }
7293 } else
7294 px = curproxy;
7295
7296 srv = findserver(px, sname);
7297 if (!srv) {
7298 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7299 proxy_type_str(curproxy), curproxy->id,
7300 newsrv->id, sname);
7301 cfgerr++;
7302 goto next_srv;
7303 }
7304
Willy Tarreau32091232014-05-16 13:52:00 +02007305 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7306 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7307 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007308 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007309 "tracking as it does not have any check nor agent enabled.\n",
7310 proxy_type_str(curproxy), curproxy->id,
7311 newsrv->id, px->id, srv->id);
7312 cfgerr++;
7313 goto next_srv;
7314 }
7315
7316 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7317
7318 if (loop) {
7319 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7320 "belongs to a tracking chain looping back to %s/%s.\n",
7321 proxy_type_str(curproxy), curproxy->id,
7322 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007323 cfgerr++;
7324 goto next_srv;
7325 }
7326
7327 if (curproxy != px &&
7328 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7329 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7330 "tracking: disable-on-404 option inconsistency.\n",
7331 proxy_type_str(curproxy), curproxy->id,
7332 newsrv->id, px->id, srv->id);
7333 cfgerr++;
7334 goto next_srv;
7335 }
7336
7337 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007338 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007339 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007340 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007341 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007342 }
7343
7344 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007345 newsrv->tracknext = srv->trackers;
7346 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007347
7348 free(newsrv->trackit);
7349 newsrv->trackit = NULL;
7350 }
7351 next_srv:
7352 newsrv = newsrv->next;
7353 }
7354
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007355 /* We have to initialize the server lookup mechanism depending
7356 * on what LB algorithm was choosen.
7357 */
7358
7359 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7360 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7361 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007362 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7363 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7364 init_server_map(curproxy);
7365 } else {
7366 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7367 fwrr_init_server_groups(curproxy);
7368 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007369 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007370
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007371 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007372 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7373 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7374 fwlc_init_server_tree(curproxy);
7375 } else {
7376 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7377 fas_init_server_tree(curproxy);
7378 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007379 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007380
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007381 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007382 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7383 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7384 chash_init_server_tree(curproxy);
7385 } else {
7386 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7387 init_server_map(curproxy);
7388 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007389 break;
7390 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007391
7392 if (curproxy->options & PR_O_LOGASAP)
7393 curproxy->to_log &= ~LW_BYTES;
7394
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007395 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007396 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007397 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7398 proxy_type_str(curproxy), curproxy->id);
7399 err_code |= ERR_WARN;
7400 }
7401
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007402 if (curproxy->mode != PR_MODE_HTTP) {
7403 int optnum;
7404
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007405 if (curproxy->uri_auth) {
7406 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7407 proxy_type_str(curproxy), curproxy->id);
7408 err_code |= ERR_WARN;
7409 curproxy->uri_auth = NULL;
7410 }
7411
Willy Tarreau87cf5142011-08-19 22:57:24 +02007412 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007413 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7414 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7415 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007416 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007417 }
7418
7419 if (curproxy->options & PR_O_ORGTO) {
7420 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7421 "originalto", proxy_type_str(curproxy), curproxy->id);
7422 err_code |= ERR_WARN;
7423 curproxy->options &= ~PR_O_ORGTO;
7424 }
7425
7426 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7427 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7428 (curproxy->cap & cfg_opts[optnum].cap) &&
7429 (curproxy->options & cfg_opts[optnum].val)) {
7430 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7431 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7432 err_code |= ERR_WARN;
7433 curproxy->options &= ~cfg_opts[optnum].val;
7434 }
7435 }
7436
7437 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7438 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7439 (curproxy->cap & cfg_opts2[optnum].cap) &&
7440 (curproxy->options2 & cfg_opts2[optnum].val)) {
7441 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7442 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7443 err_code |= ERR_WARN;
7444 curproxy->options2 &= ~cfg_opts2[optnum].val;
7445 }
7446 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007447
Pieter Baauwd551fb52013-05-08 22:49:23 +02007448#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007449 if (curproxy->conn_src.bind_hdr_occ) {
7450 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007451 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007452 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007453 err_code |= ERR_WARN;
7454 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007455#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007456 }
7457
Willy Tarreaubaaee002006-06-26 02:48:02 +02007458 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007459 * ensure that we're not cross-dressing a TCP server into HTTP.
7460 */
7461 newsrv = curproxy->srv;
7462 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007463 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007464 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7465 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007466 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007467 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007468
Willy Tarreau0cec3312011-10-31 13:49:26 +01007469 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7470 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7471 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7472 err_code |= ERR_WARN;
7473 }
7474
Willy Tarreauc93cd162014-05-13 15:54:22 +02007475 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007476 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7477 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7478 err_code |= ERR_WARN;
7479 }
7480
Pieter Baauwd551fb52013-05-08 22:49:23 +02007481#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007482 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7483 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007484 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 +01007485 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007486 err_code |= ERR_WARN;
7487 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007488#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007489 newsrv = newsrv->next;
7490 }
7491
Willy Tarreaue42bd962014-09-16 16:21:19 +02007492 /* check if we have a frontend with "tcp-request content" looking at L7
7493 * with no inspect-delay
7494 */
7495 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7496 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7497 if (trule->action == TCP_ACT_CAPTURE &&
7498 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7499 break;
7500 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7501 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7502 break;
7503 }
7504
7505 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7506 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7507 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7508 " This means that these rules will randomly find their contents. This can be fixed by"
7509 " setting the tcp-request inspect-delay.\n",
7510 proxy_type_str(curproxy), curproxy->id);
7511 err_code |= ERR_WARN;
7512 }
7513 }
7514
Willy Tarreauc1a21672009-08-16 22:37:44 +02007515 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007516 if (!curproxy->accept)
7517 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007518
Willy Tarreauc1a21672009-08-16 22:37:44 +02007519 if (curproxy->tcp_req.inspect_delay ||
7520 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007521 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007522
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007523 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007524 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007525 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007526 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007527
7528 /* both TCP and HTTP must check switching rules */
7529 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7530 }
7531
7532 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007533 if (curproxy->tcp_req.inspect_delay ||
7534 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7535 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7536
Emeric Brun97679e72010-09-23 17:56:44 +02007537 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7538 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7539
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007540 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007541 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007542 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007543 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007544
7545 /* If the backend does requires RDP cookie persistence, we have to
7546 * enable the corresponding analyser.
7547 */
7548 if (curproxy->options2 & PR_O2_RDPC_PRST)
7549 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7550 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007551 }
7552
7553 /***********************************************************/
7554 /* At this point, target names have already been resolved. */
7555 /***********************************************************/
7556
7557 /* Check multi-process mode compatibility */
7558
7559 if (global.nbproc > 1 && global.stats_fe) {
7560 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7561 unsigned long mask;
7562
7563 mask = nbits(global.nbproc);
7564 if (global.stats_fe->bind_proc)
7565 mask &= global.stats_fe->bind_proc;
7566
7567 if (bind_conf->bind_proc)
7568 mask &= bind_conf->bind_proc;
7569
7570 /* stop here if more than one process is used */
7571 if (popcount(mask) > 1)
7572 break;
7573 }
7574 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7575 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");
7576 }
7577 }
7578
7579 /* Make each frontend inherit bind-process from its listeners when not specified. */
7580 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7581 if (curproxy->bind_proc)
7582 continue;
7583
7584 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7585 unsigned long mask;
7586
7587 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7588 curproxy->bind_proc |= mask;
7589 }
7590
7591 if (!curproxy->bind_proc)
7592 curproxy->bind_proc = ~0UL;
7593 }
7594
7595 if (global.stats_fe) {
7596 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7597 unsigned long mask;
7598
7599 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7600 global.stats_fe->bind_proc |= mask;
7601 }
7602 if (!global.stats_fe->bind_proc)
7603 global.stats_fe->bind_proc = ~0UL;
7604 }
7605
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007606 /* propagate bindings from frontends to backends. Don't do it if there
7607 * are any fatal errors as we must not call it with unresolved proxies.
7608 */
7609 if (!cfgerr) {
7610 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7611 if (curproxy->cap & PR_CAP_FE)
7612 propagate_processes(curproxy, NULL);
7613 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007614 }
7615
7616 /* Bind each unbound backend to all processes when not specified. */
7617 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7618 if (curproxy->bind_proc)
7619 continue;
7620 curproxy->bind_proc = ~0UL;
7621 }
7622
7623 /*******************************************************/
7624 /* At this step, all proxies have a non-null bind_proc */
7625 /*******************************************************/
7626
7627 /* perform the final checks before creating tasks */
7628
7629 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7630 struct listener *listener;
7631 unsigned int next_id;
7632 int nbproc;
7633
7634 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007635
Emeric Brunc52962f2012-11-15 18:28:02 +01007636#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007637 /* Configure SSL for each bind line.
7638 * Note: if configuration fails at some point, the ->ctx member
7639 * remains NULL so that listeners can later detach.
7640 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007641 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007642 int alloc_ctx;
7643
Emeric Brunc52962f2012-11-15 18:28:02 +01007644 if (!bind_conf->is_ssl) {
7645 if (bind_conf->default_ctx) {
7646 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7647 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7648 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007649 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007650 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007651 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007652 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007653 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007654 cfgerr++;
7655 continue;
7656 }
7657
Emeric Brun8dc60392014-05-09 13:52:00 +02007658 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007659 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007660 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7661 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");
7662 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007663 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007664 cfgerr++;
7665 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007666 }
7667
Emeric Brunfc0421f2012-09-07 17:30:07 +02007668 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007669 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007670 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007671#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007672
Willy Tarreaue6b98942007-10-29 01:09:36 +01007673 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007674 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007675 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007676 if (!listener->luid) {
7677 /* listener ID not set, use automatic numbering with first
7678 * spare entry starting with next_luid.
7679 */
7680 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7681 listener->conf.id.key = listener->luid = next_id;
7682 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007683 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007684 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007685
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007686 /* enable separate counters */
7687 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7688 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007689 if (!listener->name)
7690 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007691 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007692
Willy Tarreaue6b98942007-10-29 01:09:36 +01007693 if (curproxy->options & PR_O_TCP_NOLING)
7694 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007695 if (!listener->maxconn)
7696 listener->maxconn = curproxy->maxconn;
7697 if (!listener->backlog)
7698 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007699 if (!listener->maxaccept)
7700 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7701
7702 /* we want to have an optimal behaviour on single process mode to
7703 * maximize the work at once, but in multi-process we want to keep
7704 * some fairness between processes, so we target half of the max
7705 * number of events to be balanced over all the processes the proxy
7706 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7707 * used to disable the limit.
7708 */
7709 if (listener->maxaccept > 0) {
7710 if (nbproc > 1)
7711 listener->maxaccept = (listener->maxaccept + 1) / 2;
7712 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7713 }
7714
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007715 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007716 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007717 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007718 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007719
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007720 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7721 listener->options |= LI_O_TCP_RULES;
7722
Willy Tarreaude3041d2010-05-31 10:56:17 +02007723 if (curproxy->mon_mask.s_addr)
7724 listener->options |= LI_O_CHK_MONNET;
7725
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007726 /* smart accept mode is automatic in HTTP mode */
7727 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007728 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007729 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7730 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007731 }
7732
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007733 /* Release unused SSL configs */
7734 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7735 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007736 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007737#ifdef USE_OPENSSL
7738 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007739 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007740 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007741 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007742 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007743 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007744#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007745 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007746
Willy Tarreau102df612014-05-07 23:56:38 +02007747 if (nbproc > 1) {
7748 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007749 int count, maxproc = 0;
7750
7751 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7752 count = popcount(bind_conf->bind_proc);
7753 if (count > maxproc)
7754 maxproc = count;
7755 }
7756 /* backends have 0, frontends have 1 or more */
7757 if (maxproc != 1)
7758 Warning("Proxy '%s': in multi-process mode, stats will be"
7759 " limited to process assigned to the current request.\n",
7760 curproxy->id);
7761
Willy Tarreau102df612014-05-07 23:56:38 +02007762 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7763 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7764 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007765 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007766 }
Willy Tarreau102df612014-05-07 23:56:38 +02007767 if (curproxy->appsession_name) {
7768 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7769 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007770 }
Willy Tarreau102df612014-05-07 23:56:38 +02007771 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7772 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7773 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007774 }
7775 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007776
7777 /* create the task associated with the proxy */
7778 curproxy->task = task_new();
7779 if (curproxy->task) {
7780 curproxy->task->context = curproxy;
7781 curproxy->task->process = manage_proxy;
7782 /* no need to queue, it will be done automatically if some
7783 * listener gets limited.
7784 */
7785 curproxy->task->expire = TICK_ETERNITY;
7786 } else {
7787 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7788 curproxy->id);
7789 cfgerr++;
7790 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007791 }
7792
Willy Tarreaufbb78422011-06-05 15:38:35 +02007793 /* automatically compute fullconn if not set. We must not do it in the
7794 * loop above because cross-references are not yet fully resolved.
7795 */
7796 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7797 /* If <fullconn> is not set, let's set it to 10% of the sum of
7798 * the possible incoming frontend's maxconns.
7799 */
7800 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7801 struct proxy *fe;
7802 int total = 0;
7803
7804 /* sum up the number of maxconns of frontends which
7805 * reference this backend at least once or which are
7806 * the same one ('listen').
7807 */
7808 for (fe = proxy; fe; fe = fe->next) {
7809 struct switching_rule *rule;
7810 struct hdr_exp *exp;
7811 int found = 0;
7812
7813 if (!(fe->cap & PR_CAP_FE))
7814 continue;
7815
7816 if (fe == curproxy) /* we're on a "listen" instance */
7817 found = 1;
7818
7819 if (fe->defbe.be == curproxy) /* "default_backend" */
7820 found = 1;
7821
7822 /* check if a "use_backend" rule matches */
7823 if (!found) {
7824 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007825 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007826 found = 1;
7827 break;
7828 }
7829 }
7830 }
7831
7832 /* check if a "reqsetbe" rule matches */
7833 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7834 if (exp->action == ACT_SETBE &&
7835 (struct proxy *)exp->replace == curproxy) {
7836 found = 1;
7837 break;
7838 }
7839 }
7840
7841 /* now we've checked all possible ways to reference a backend
7842 * from a frontend.
7843 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007844 if (!found)
7845 continue;
7846 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007847 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007848 /* we have the sum of the maxconns in <total>. We only
7849 * keep 10% of that sum to set the default fullconn, with
7850 * a hard minimum of 1 (to avoid a divide by zero).
7851 */
7852 curproxy->fullconn = (total + 9) / 10;
7853 if (!curproxy->fullconn)
7854 curproxy->fullconn = 1;
7855 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007856 }
7857
Willy Tarreau056f5682010-06-06 15:51:11 +02007858 /* initialize stick-tables on backend capable proxies. This must not
7859 * be done earlier because the data size may be discovered while parsing
7860 * other proxies.
7861 */
Godbach9703e662013-12-11 21:11:41 +08007862 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007863 if (curproxy->state == PR_STSTOPPED)
7864 continue;
7865
Godbach9703e662013-12-11 21:11:41 +08007866 if (!stktable_init(&curproxy->table)) {
7867 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7868 cfgerr++;
7869 }
7870 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007871
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007872 /*
7873 * Recount currently required checks.
7874 */
7875
7876 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7877 int optnum;
7878
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007879 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7880 if (curproxy->options & cfg_opts[optnum].val)
7881 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007882
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007883 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7884 if (curproxy->options2 & cfg_opts2[optnum].val)
7885 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007886 }
7887
Willy Tarreau122541c2011-09-07 21:24:49 +02007888 if (peers) {
7889 struct peers *curpeers = peers, **last;
7890 struct peer *p, *pb;
7891
7892 /* Remove all peers sections which don't have a valid listener.
7893 * This can happen when a peers section is never referenced and
7894 * does not contain a local peer.
7895 */
7896 last = &peers;
7897 while (*last) {
7898 curpeers = *last;
7899 if (curpeers->peers_fe) {
7900 last = &curpeers->next;
7901 continue;
7902 }
7903
7904 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7905 curpeers->id, localpeer);
7906
7907 p = curpeers->remote;
7908 while (p) {
7909 pb = p->next;
7910 free(p->id);
7911 free(p);
7912 p = pb;
7913 }
7914
7915 /* Destroy and unlink this curpeers section.
7916 * Note: curpeers is backed up into *last.
7917 */
7918 free(curpeers->id);
7919 curpeers = curpeers->next;
7920 free(*last);
7921 *last = curpeers;
7922 }
7923 }
7924
Simon Horman0d16a402015-01-30 11:22:58 +09007925 if (mailers) {
7926 struct mailers *curmailers = mailers, **last;
7927 struct mailer *m, *mb;
7928
7929 /* Remove all mailers sections which don't have a valid listener.
7930 * This can happen when a mailers section is never referenced.
7931 */
7932 last = &mailers;
7933 while (*last) {
7934 curmailers = *last;
7935 if (curmailers->users) {
7936 last = &curmailers->next;
7937 continue;
7938 }
7939
7940 Warning("Removing incomplete section 'mailers %s'.\n",
7941 curmailers->id);
7942
7943 m = curmailers->mailer_list;
7944 while (m) {
7945 mb = m->next;
7946 free(m->id);
7947 free(m);
7948 m = mb;
7949 }
7950
7951 /* Destroy and unlink this curmailers section.
7952 * Note: curmailers is backed up into *last.
7953 */
7954 free(curmailers->id);
7955 curmailers = curmailers->next;
7956 free(*last);
7957 *last = curmailers;
7958 }
7959 }
7960
Willy Tarreau34eb6712011-10-24 18:15:04 +02007961 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007962 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007963 MEM_F_SHARED);
7964
Willy Tarreaubb925012009-07-23 13:36:36 +02007965 if (cfgerr > 0)
7966 err_code |= ERR_ALERT | ERR_FATAL;
7967 out:
7968 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007969}
7970
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007971/*
7972 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7973 * parsing sessions.
7974 */
7975void cfg_register_keywords(struct cfg_kw_list *kwl)
7976{
7977 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7978}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007979
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007980/*
7981 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7982 */
7983void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7984{
7985 LIST_DEL(&kwl->list);
7986 LIST_INIT(&kwl->list);
7987}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007988
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007989/* this function register new section in the haproxy configuration file.
7990 * <section_name> is the name of this new section and <section_parser>
7991 * is the called parser. If two section declaration have the same name,
7992 * only the first declared is used.
7993 */
7994int cfg_register_section(char *section_name,
7995 int (*section_parser)(const char *, int, char **, int))
7996{
7997 struct cfg_section *cs;
7998
7999 cs = calloc(1, sizeof(*cs));
8000 if (!cs) {
8001 Alert("register section '%s': out of memory.\n", section_name);
8002 return 0;
8003 }
8004
8005 cs->section_name = section_name;
8006 cs->section_parser = section_parser;
8007
8008 LIST_ADDQ(&sections, &cs->list);
8009
8010 return 1;
8011}
8012
Willy Tarreaubaaee002006-06-26 02:48:02 +02008013/*
8014 * Local variables:
8015 * c-indent-level: 8
8016 * c-basic-offset: 8
8017 * End:
8018 */