blob: 5fe3ffb1eb475f126d82d770208280285efd56e9 [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 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02001865 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
1866 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01001867 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02001868
1869 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
1870
Willy Tarreau902636f2013-03-10 19:44:48 +01001871 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
1872 if (errmsg && *errmsg) {
1873 indent_msg(&errmsg, 2);
1874 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02001875 }
1876 else
1877 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
1878 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02001879 err_code |= ERR_FATAL;
1880 goto out;
1881 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02001882
1883 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01001884 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001885 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
1886 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001887 l->accept = session_accept;
1888 l->handler = process_session;
1889 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1890 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1891 global.maxsock += l->maxconn;
1892 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001893 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001894 else {
1895 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1896 file, linenum, args[0], args[1],
1897 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1898 err_code |= ERR_FATAL;
1899 goto out;
1900 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001901 }
1902 } /* neither "peer" nor "peers" */
1903 else if (*args[0] != 0) {
1904 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
1907 }
1908
1909out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001910 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001911 return err_code;
1912}
1913
Simon Horman0d16a402015-01-30 11:22:58 +09001914
1915/*
1916 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1917 * Returns the error code, 0 if OK, or any combination of :
1918 * - ERR_ABORT: must abort ASAP
1919 * - ERR_FATAL: we can continue parsing but not start the service
1920 * - ERR_WARN: a warning has been emitted
1921 * - ERR_ALERT: an alert has been emitted
1922 * Only the two first ones can stop processing, the two others are just
1923 * indicators.
1924 */
1925int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1926{
1927 static struct mailers *curmailers = NULL;
1928 struct mailer *newmailer = NULL;
1929 const char *err;
1930 int err_code = 0;
1931 char *errmsg = NULL;
1932
1933 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1934 if (!*args[1]) {
1935 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1936 err_code |= ERR_ALERT | ERR_ABORT;
1937 goto out;
1938 }
1939
1940 err = invalid_char(args[1]);
1941 if (err) {
1942 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1943 file, linenum, *err, args[0], args[1]);
1944 err_code |= ERR_ALERT | ERR_ABORT;
1945 goto out;
1946 }
1947
1948 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1949 /*
1950 * If there are two proxies with the same name only following
1951 * combinations are allowed:
1952 */
1953 if (strcmp(curmailers->id, args[1]) == 0) {
1954 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1955 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1956 err_code |= ERR_WARN;
1957 }
1958 }
1959
1960 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1961 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1962 err_code |= ERR_ALERT | ERR_ABORT;
1963 goto out;
1964 }
1965
1966 curmailers->next = mailers;
1967 mailers = curmailers;
1968 curmailers->conf.file = strdup(file);
1969 curmailers->conf.line = linenum;
1970 curmailers->id = strdup(args[1]);
1971 }
1972 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1973 struct sockaddr_storage *sk;
1974 int port1, port2;
1975 struct protocol *proto;
1976
1977 if (!*args[2]) {
1978 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1979 file, linenum, args[0]);
1980 err_code |= ERR_ALERT | ERR_FATAL;
1981 goto out;
1982 }
1983
1984 err = invalid_char(args[1]);
1985 if (err) {
1986 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1987 file, linenum, *err, args[1]);
1988 err_code |= ERR_ALERT | ERR_FATAL;
1989 goto out;
1990 }
1991
1992 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
1993 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1994 err_code |= ERR_ALERT | ERR_ABORT;
1995 goto out;
1996 }
1997
1998 /* the mailers are linked backwards first */
1999 curmailers->count++;
2000 newmailer->next = curmailers->mailer_list;
2001 curmailers->mailer_list = newmailer;
2002 newmailer->mailers = curmailers;
2003 newmailer->conf.file = strdup(file);
2004 newmailer->conf.line = linenum;
2005
2006 newmailer->id = strdup(args[1]);
2007
2008 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2009 if (!sk) {
2010 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2011 err_code |= ERR_ALERT | ERR_FATAL;
2012 goto out;
2013 }
2014
2015 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002016 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2017 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002018 file, linenum, args[0], args[1]);
2019 err_code |= ERR_ALERT | ERR_FATAL;
2020 goto out;
2021 }
2022
2023 if (port1 != port2) {
2024 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2025 file, linenum, args[0], args[1], args[2]);
2026 err_code |= ERR_ALERT | ERR_FATAL;
2027 goto out;
2028 }
2029
2030 if (!port1) {
2031 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2032 file, linenum, args[0], args[1], args[2]);
2033 err_code |= ERR_ALERT | ERR_FATAL;
2034 goto out;
2035 }
2036
2037 newmailer->addr = *sk;
2038 newmailer->proto = proto;
2039 newmailer->xprt = &raw_sock;
2040 newmailer->sock_init_arg = NULL;
2041 } /* neither "mailer" nor "mailers" */
2042 else if (*args[0] != 0) {
2043 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
2046 }
2047
2048out:
2049 free(errmsg);
2050 return err_code;
2051}
2052
Simon Horman9dc49962015-01-30 11:22:59 +09002053static void free_email_alert(struct proxy *p)
2054{
2055 free(p->email_alert.mailers.name);
2056 p->email_alert.mailers.name = NULL;
2057 free(p->email_alert.from);
2058 p->email_alert.from = NULL;
2059 free(p->email_alert.to);
2060 p->email_alert.to = NULL;
2061 free(p->email_alert.myhostname);
2062 p->email_alert.myhostname = NULL;
2063}
2064
Willy Tarreau3842f002009-06-14 11:39:52 +02002065int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002066{
2067 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002068 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002069 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002070 int rc;
2071 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002072 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002073 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002074 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002075 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002076 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002077
Willy Tarreau977b8e42006-12-29 14:19:17 +01002078 if (!strcmp(args[0], "listen"))
2079 rc = PR_CAP_LISTEN;
2080 else if (!strcmp(args[0], "frontend"))
2081 rc = PR_CAP_FE | PR_CAP_RS;
2082 else if (!strcmp(args[0], "backend"))
2083 rc = PR_CAP_BE | PR_CAP_RS;
2084 else if (!strcmp(args[0], "ruleset"))
2085 rc = PR_CAP_RS;
2086 else
2087 rc = PR_CAP_NONE;
2088
2089 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002090 struct ebpt_node *node;
2091
Willy Tarreaubaaee002006-06-26 02:48:02 +02002092 if (!*args[1]) {
2093 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2094 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2095 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002096 err_code |= ERR_ALERT | ERR_ABORT;
2097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002098 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002099
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002100 err = invalid_char(args[1]);
2101 if (err) {
2102 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2103 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002104 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002105 }
2106
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002107 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2108 curproxy = container_of(node, struct proxy, conf.by_name);
2109
2110 if (strcmp(curproxy->id, args[1]) != 0)
2111 break;
2112
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002113 /*
2114 * If there are two proxies with the same name only following
2115 * combinations are allowed:
2116 *
2117 * listen backend frontend ruleset
2118 * listen - - - -
2119 * backend - - OK -
2120 * frontend - OK - -
2121 * ruleset - - - -
2122 */
2123
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002124 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2125 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002126 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2127 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2128 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002129 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002130 }
2131 }
2132
Willy Tarreaubaaee002006-06-26 02:48:02 +02002133 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2134 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002135 err_code |= ERR_ALERT | ERR_ABORT;
2136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002137 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002138
Willy Tarreau97cb7802010-01-03 20:23:58 +01002139 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002140 curproxy->next = proxy;
2141 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002142 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2143 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002144 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002145 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002146 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002147 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002148
2149 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002150 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002151 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002152
Willy Tarreau4348fad2012-09-20 16:48:07 +02002153 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2154
Willy Tarreau902636f2013-03-10 19:44:48 +01002155 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2156 if (errmsg && *errmsg) {
2157 indent_msg(&errmsg, 2);
2158 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002159 }
2160 else
2161 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2162 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002163 err_code |= ERR_FATAL;
2164 goto out;
2165 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002166
Willy Tarreau4348fad2012-09-20 16:48:07 +02002167 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002168 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002169 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002170 }
2171
2172 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002173 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002174 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002175
Willy Tarreaubaaee002006-06-26 02:48:02 +02002176 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002178 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002179 curproxy->no_options = defproxy.no_options;
2180 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002181 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002182 curproxy->except_net = defproxy.except_net;
2183 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002184 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002185 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002186
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002187 if (defproxy.fwdfor_hdr_len) {
2188 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2189 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2190 }
2191
Willy Tarreaub86db342009-11-30 11:50:16 +01002192 if (defproxy.orgto_hdr_len) {
2193 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2194 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2195 }
2196
Mark Lamourinec2247f02012-01-04 13:02:01 -05002197 if (defproxy.server_id_hdr_len) {
2198 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2199 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2200 }
2201
Willy Tarreau977b8e42006-12-29 14:19:17 +01002202 if (curproxy->cap & PR_CAP_FE) {
2203 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002204 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002205 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002206
2207 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002208 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2209 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002210
2211 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2212 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002213
Willy Tarreau977b8e42006-12-29 14:19:17 +01002214 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002215 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002216 curproxy->fullconn = defproxy.fullconn;
2217 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002218 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002219
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002220 if (defproxy.check_req) {
2221 curproxy->check_req = calloc(1, defproxy.check_len);
2222 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2223 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002224 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002225
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002226 if (defproxy.expect_str) {
2227 curproxy->expect_str = strdup(defproxy.expect_str);
2228 if (defproxy.expect_regex) {
2229 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002230 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2231 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002232 }
2233 }
2234
Willy Tarreau67402132012-05-31 20:40:20 +02002235 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002236 if (defproxy.cookie_name)
2237 curproxy->cookie_name = strdup(defproxy.cookie_name);
2238 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002239 if (defproxy.cookie_domain)
2240 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002241
Willy Tarreau31936852010-10-06 16:59:56 +02002242 if (defproxy.cookie_maxidle)
2243 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2244
2245 if (defproxy.cookie_maxlife)
2246 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2247
Emeric Brun647caf12009-06-30 17:57:00 +02002248 if (defproxy.rdp_cookie_name)
2249 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2250 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2251
Willy Tarreau01732802007-11-01 22:48:15 +01002252 if (defproxy.url_param_name)
2253 curproxy->url_param_name = strdup(defproxy.url_param_name);
2254 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002255
Benoitaffb4812009-03-25 13:02:10 +01002256 if (defproxy.hh_name)
2257 curproxy->hh_name = strdup(defproxy.hh_name);
2258 curproxy->hh_len = defproxy.hh_len;
2259 curproxy->hh_match_domain = defproxy.hh_match_domain;
2260
Willy Tarreauef9a3602012-12-08 22:29:20 +01002261 if (defproxy.conn_src.iface_name)
2262 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2263 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002264 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002265#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002266 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002267#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002269
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002270 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002271 if (defproxy.capture_name)
2272 curproxy->capture_name = strdup(defproxy.capture_name);
2273 curproxy->capture_namelen = defproxy.capture_namelen;
2274 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002276
Willy Tarreau977b8e42006-12-29 14:19:17 +01002277 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002278 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002279 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002280 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002281 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002282 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002283 curproxy->mon_net = defproxy.mon_net;
2284 curproxy->mon_mask = defproxy.mon_mask;
2285 if (defproxy.monitor_uri)
2286 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2287 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002288 if (defproxy.defbe.name)
2289 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002290
2291 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002292 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2293 if (curproxy->conf.logformat_string &&
2294 curproxy->conf.logformat_string != default_http_log_format &&
2295 curproxy->conf.logformat_string != default_tcp_log_format &&
2296 curproxy->conf.logformat_string != clf_http_log_format)
2297 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2298
2299 if (defproxy.conf.lfs_file) {
2300 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2301 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2302 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002303 }
2304
2305 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002306 curproxy->timeout.connect = defproxy.timeout.connect;
2307 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002308 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002309 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002310 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002311 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002312 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002313 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002314 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002315 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002316 }
2317
Willy Tarreaubaaee002006-06-26 02:48:02 +02002318 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002319 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002320
2321 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002322 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002323 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002324 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002325 LIST_INIT(&node->list);
2326 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2327 }
2328
Willy Tarreau62a61232013-04-12 18:13:46 +02002329 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2330 if (curproxy->conf.uniqueid_format_string)
2331 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2332
Willy Tarreau094af4e2015-01-07 15:03:42 +01002333 if (defproxy.log_tag)
2334 curproxy->log_tag = strdup(defproxy.log_tag);
2335
Willy Tarreau62a61232013-04-12 18:13:46 +02002336 if (defproxy.conf.uif_file) {
2337 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2338 curproxy->conf.uif_line = defproxy.conf.uif_line;
2339 }
William Lallemanda73203e2012-03-12 12:48:57 +01002340
2341 /* copy default header unique id */
2342 if (defproxy.header_unique_id)
2343 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2344
William Lallemand82fe75c2012-10-23 10:25:10 +02002345 /* default compression options */
2346 if (defproxy.comp != NULL) {
2347 curproxy->comp = calloc(1, sizeof(struct comp));
2348 curproxy->comp->algos = defproxy.comp->algos;
2349 curproxy->comp->types = defproxy.comp->types;
2350 }
2351
Willy Tarreaubaaee002006-06-26 02:48:02 +02002352 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002353 curproxy->conf.used_listener_id = EB_ROOT;
2354 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002355
Simon Horman98637e52014-06-20 12:30:16 +09002356 if (defproxy.check_path)
2357 curproxy->check_path = strdup(defproxy.check_path);
2358 if (defproxy.check_command)
2359 curproxy->check_command = strdup(defproxy.check_command);
2360
Simon Horman9dc49962015-01-30 11:22:59 +09002361 if (defproxy.email_alert.mailers.name)
2362 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2363 if (defproxy.email_alert.from)
2364 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2365 if (defproxy.email_alert.to)
2366 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2367 if (defproxy.email_alert.myhostname)
2368 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002369 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002370
Willy Tarreau93893792009-07-23 13:19:11 +02002371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002372 }
2373 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2374 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002375 /* FIXME-20070101: we should do this too at the end of the
2376 * config parsing to free all default values.
2377 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002378 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002379 free(defproxy.check_command);
2380 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002381 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002382 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002383 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002384 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002385 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002386 free(defproxy.capture_name);
2387 free(defproxy.monitor_uri);
2388 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002389 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002390 free(defproxy.fwdfor_hdr_name);
2391 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002392 free(defproxy.orgto_hdr_name);
2393 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002394 free(defproxy.server_id_hdr_name);
2395 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002396 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002397 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002398 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002399 free(defproxy.expect_regex);
2400 defproxy.expect_regex = NULL;
2401 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002402
Willy Tarreau62a61232013-04-12 18:13:46 +02002403 if (defproxy.conf.logformat_string != default_http_log_format &&
2404 defproxy.conf.logformat_string != default_tcp_log_format &&
2405 defproxy.conf.logformat_string != clf_http_log_format)
2406 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002407
Willy Tarreau62a61232013-04-12 18:13:46 +02002408 free(defproxy.conf.uniqueid_format_string);
2409 free(defproxy.conf.lfs_file);
2410 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002411 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002412 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002413
Willy Tarreaua534fea2008-08-03 12:19:50 +02002414 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002415 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002416
Willy Tarreaubaaee002006-06-26 02:48:02 +02002417 /* we cannot free uri_auth because it might already be used */
2418 init_default_instance();
2419 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002420 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2421 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002422 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002423 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002424 }
2425 else if (curproxy == NULL) {
2426 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002427 err_code |= ERR_ALERT | ERR_FATAL;
2428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002429 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002430
2431 /* update the current file and line being parsed */
2432 curproxy->conf.args.file = curproxy->conf.file;
2433 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002434
2435 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002436 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2437 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2438 if (err_code & ERR_FATAL)
2439 goto out;
2440 }
2441 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002442 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002443 int cur_arg;
2444
Willy Tarreaubaaee002006-06-26 02:48:02 +02002445 if (curproxy == &defproxy) {
2446 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002450 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002451 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002452
Willy Tarreau24709282013-03-10 21:32:12 +01002453 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002454 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002455 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002458 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002459
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002460 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002461
2462 /* use default settings for unix sockets */
2463 bind_conf->ux.uid = global.unix_bind.ux.uid;
2464 bind_conf->ux.gid = global.unix_bind.ux.gid;
2465 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002466
2467 /* NOTE: the following line might create several listeners if there
2468 * are comma-separated IPs or port ranges. So all further processing
2469 * will have to be applied to all listeners created after last_listen.
2470 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002471 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2472 if (errmsg && *errmsg) {
2473 indent_msg(&errmsg, 2);
2474 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002475 }
2476 else
2477 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2478 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002479 err_code |= ERR_ALERT | ERR_FATAL;
2480 goto out;
2481 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002482
Willy Tarreau4348fad2012-09-20 16:48:07 +02002483 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2484 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002485 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002486 }
2487
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002488 cur_arg = 2;
2489 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002490 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002491 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002492 char *err;
2493
Willy Tarreau26982662012-09-12 23:17:10 +02002494 kw = bind_find_kw(args[cur_arg]);
2495 if (kw) {
2496 char *err = NULL;
2497 int code;
2498
2499 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002500 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2501 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002502 cur_arg += 1 + kw->skip ;
2503 err_code |= ERR_ALERT | ERR_FATAL;
2504 goto out;
2505 }
2506
Willy Tarreau4348fad2012-09-20 16:48:07 +02002507 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002508 err_code |= code;
2509
2510 if (code) {
2511 if (err && *err) {
2512 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002513 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002514 }
2515 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002516 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2517 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002518 if (code & ERR_FATAL) {
2519 free(err);
2520 cur_arg += 1 + kw->skip;
2521 goto out;
2522 }
2523 }
2524 free(err);
2525 cur_arg += 1 + kw->skip;
2526 continue;
2527 }
2528
Willy Tarreau8638f482012-09-18 18:01:17 +02002529 err = NULL;
2530 if (!bind_dumped) {
2531 bind_dump_kws(&err);
2532 indent_msg(&err, 4);
2533 bind_dumped = 1;
2534 }
2535
2536 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2537 file, linenum, args[0], args[1], args[cur_arg],
2538 err ? " Registered keywords :" : "", err ? err : "");
2539 free(err);
2540
Willy Tarreau93893792009-07-23 13:19:11 +02002541 err_code |= ERR_ALERT | ERR_FATAL;
2542 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002543 }
Willy Tarreau93893792009-07-23 13:19:11 +02002544 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002545 }
2546 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002547 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002548 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2549 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002550 err_code |= ERR_ALERT | ERR_FATAL;
2551 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002552 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002553 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002554 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002555
Willy Tarreaubaaee002006-06-26 02:48:02 +02002556 /* flush useless bits */
2557 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002560 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
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 Tarreau1c47f852006-07-09 08:22:27 +02002564 if (!*args[1]) {
2565 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2566 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002567 err_code |= ERR_ALERT | ERR_FATAL;
2568 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002569 }
2570
Willy Tarreaua534fea2008-08-03 12:19:50 +02002571 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002572 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002573 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002574 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002575 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2576
Willy Tarreau93893792009-07-23 13:19:11 +02002577 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2580 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2581 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2582 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2583 else {
2584 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002585 err_code |= ERR_ALERT | ERR_FATAL;
2586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587 }
2588 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002589 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002590 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002591
2592 if (curproxy == &defproxy) {
2593 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2594 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002597 }
2598
2599 if (!*args[1]) {
2600 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2601 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002602 err_code |= ERR_ALERT | ERR_FATAL;
2603 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002604 }
2605
2606 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002607 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002608
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002609 if (curproxy->uuid <= 0) {
2610 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002611 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002612 err_code |= ERR_ALERT | ERR_FATAL;
2613 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002614 }
2615
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002616 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2617 if (node) {
2618 struct proxy *target = container_of(node, struct proxy, conf.id);
2619 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2620 file, linenum, proxy_type_str(curproxy), curproxy->id,
2621 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2622 err_code |= ERR_ALERT | ERR_FATAL;
2623 goto out;
2624 }
2625 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002626 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002627 else if (!strcmp(args[0], "description")) {
2628 int i, len=0;
2629 char *d;
2630
Cyril Bonté99ed3272010-01-24 23:29:44 +01002631 if (curproxy == &defproxy) {
2632 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2633 file, linenum, args[0]);
2634 err_code |= ERR_ALERT | ERR_FATAL;
2635 goto out;
2636 }
2637
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002638 if (!*args[1]) {
2639 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2640 file, linenum, args[0]);
2641 return -1;
2642 }
2643
Willy Tarreau348acfe2014-04-14 15:00:39 +02002644 for (i = 1; *args[i]; i++)
2645 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002646
2647 d = (char *)calloc(1, len);
2648 curproxy->desc = d;
2649
Willy Tarreau348acfe2014-04-14 15:00:39 +02002650 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2651 for (i = 2; *args[i]; i++)
2652 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002653
2654 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002655 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2656 curproxy->state = PR_STSTOPPED;
2657 }
2658 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2659 curproxy->state = PR_STNEW;
2660 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002661 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2662 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002663 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002664
2665 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002666 unsigned int low, high;
2667
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002668 if (strcmp(args[cur_arg], "all") == 0) {
2669 set = 0;
2670 break;
2671 }
2672 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002673 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002674 }
2675 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002676 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002677 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002678 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002679 char *dash = strchr(args[cur_arg], '-');
2680
2681 low = high = str2uic(args[cur_arg]);
2682 if (dash)
2683 high = str2uic(dash + 1);
2684
2685 if (high < low) {
2686 unsigned int swap = low;
2687 low = high;
2688 high = swap;
2689 }
2690
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002691 if (low < 1 || high > LONGBITS) {
2692 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2693 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002694 err_code |= ERR_ALERT | ERR_FATAL;
2695 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002696 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002697 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002698 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002699 }
2700 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002701 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2702 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002705 }
2706 cur_arg++;
2707 }
2708 curproxy->bind_proc = set;
2709 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002710 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002711 if (curproxy == &defproxy) {
2712 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002713 err_code |= ERR_ALERT | ERR_FATAL;
2714 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002715 }
2716
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002717 err = invalid_char(args[1]);
2718 if (err) {
2719 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2720 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002721 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002722 }
2723
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002724 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002725 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2726 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002727 err_code |= ERR_ALERT | ERR_FATAL;
2728 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002729 }
2730 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2732 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002733
Willy Tarreau977b8e42006-12-29 14:19:17 +01002734 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002735 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002736
Willy Tarreaubaaee002006-06-26 02:48:02 +02002737 if (*(args[1]) == 0) {
2738 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2739 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002740 err_code |= ERR_ALERT | ERR_FATAL;
2741 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002743
Willy Tarreau67402132012-05-31 20:40:20 +02002744 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002745 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002746 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002747 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002748 curproxy->cookie_name = strdup(args[1]);
2749 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002750
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 cur_arg = 2;
2752 while (*(args[cur_arg])) {
2753 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002754 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002755 }
2756 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002757 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 }
2759 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002760 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002761 }
2762 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002763 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002764 }
2765 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002766 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002768 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002769 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002770 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002771 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002772 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002773 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002774 else if (!strcmp(args[cur_arg], "httponly")) {
2775 curproxy->ck_opts |= PR_CK_HTTPONLY;
2776 }
2777 else if (!strcmp(args[cur_arg], "secure")) {
2778 curproxy->ck_opts |= PR_CK_SECURE;
2779 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002780 else if (!strcmp(args[cur_arg], "domain")) {
2781 if (!*args[cur_arg + 1]) {
2782 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2783 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002784 err_code |= ERR_ALERT | ERR_FATAL;
2785 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002786 }
2787
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002788 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002789 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002790 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2791 " dots nor does not start with a dot."
2792 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002793 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002794 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002795 }
2796
2797 err = invalid_domainchar(args[cur_arg + 1]);
2798 if (err) {
2799 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2800 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002801 err_code |= ERR_ALERT | ERR_FATAL;
2802 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002803 }
2804
Willy Tarreau68a897b2009-12-03 23:28:34 +01002805 if (!curproxy->cookie_domain) {
2806 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2807 } else {
2808 /* one domain was already specified, add another one by
2809 * building the string which will be returned along with
2810 * the cookie.
2811 */
2812 char *new_ptr;
2813 int new_len = strlen(curproxy->cookie_domain) +
2814 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2815 new_ptr = malloc(new_len);
2816 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2817 free(curproxy->cookie_domain);
2818 curproxy->cookie_domain = new_ptr;
2819 }
Willy Tarreau31936852010-10-06 16:59:56 +02002820 cur_arg++;
2821 }
2822 else if (!strcmp(args[cur_arg], "maxidle")) {
2823 unsigned int maxidle;
2824 const char *res;
2825
2826 if (!*args[cur_arg + 1]) {
2827 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2828 file, linenum, args[cur_arg]);
2829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
2831 }
2832
2833 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2834 if (res) {
2835 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2836 file, linenum, *res, args[cur_arg]);
2837 err_code |= ERR_ALERT | ERR_FATAL;
2838 goto out;
2839 }
2840 curproxy->cookie_maxidle = maxidle;
2841 cur_arg++;
2842 }
2843 else if (!strcmp(args[cur_arg], "maxlife")) {
2844 unsigned int maxlife;
2845 const char *res;
2846
2847 if (!*args[cur_arg + 1]) {
2848 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2849 file, linenum, args[cur_arg]);
2850 err_code |= ERR_ALERT | ERR_FATAL;
2851 goto out;
2852 }
2853
2854 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2855 if (res) {
2856 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2857 file, linenum, *res, args[cur_arg]);
2858 err_code |= ERR_ALERT | ERR_FATAL;
2859 goto out;
2860 }
2861 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002862 cur_arg++;
2863 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002865 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 +02002866 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002867 err_code |= ERR_ALERT | ERR_FATAL;
2868 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002869 }
2870 cur_arg++;
2871 }
Willy Tarreau67402132012-05-31 20:40:20 +02002872 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2874 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002875 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002876 }
2877
Willy Tarreau67402132012-05-31 20:40:20 +02002878 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002879 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2880 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002881 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002882 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002883
Willy Tarreau67402132012-05-31 20:40:20 +02002884 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002885 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2886 file, linenum);
2887 err_code |= ERR_ALERT | ERR_FATAL;
2888 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002889 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002890 else if (!strcmp(args[0], "email-alert")) {
2891 if (*(args[1]) == 0) {
2892 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2893 file, linenum, args[0]);
2894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
2897
2898 if (!strcmp(args[1], "from")) {
2899 if (*(args[1]) == 0) {
2900 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2901 file, linenum, args[1]);
2902 err_code |= ERR_ALERT | ERR_FATAL;
2903 goto out;
2904 }
2905 free(curproxy->email_alert.from);
2906 curproxy->email_alert.from = strdup(args[2]);
2907 }
2908 else if (!strcmp(args[1], "mailers")) {
2909 if (*(args[1]) == 0) {
2910 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2911 file, linenum, args[1]);
2912 err_code |= ERR_ALERT | ERR_FATAL;
2913 goto out;
2914 }
2915 free(curproxy->email_alert.mailers.name);
2916 curproxy->email_alert.mailers.name = strdup(args[2]);
2917 }
2918 else if (!strcmp(args[1], "myhostname")) {
2919 if (*(args[1]) == 0) {
2920 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2921 file, linenum, args[1]);
2922 err_code |= ERR_ALERT | ERR_FATAL;
2923 goto out;
2924 }
2925 free(curproxy->email_alert.myhostname);
2926 curproxy->email_alert.myhostname = strdup(args[2]);
2927 }
Simon Horman64e34162015-02-06 11:11:57 +09002928 else if (!strcmp(args[1], "level")) {
2929 curproxy->email_alert.level = get_log_level(args[2]);
2930 if (curproxy->email_alert.level < 0) {
2931 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2932 file, linenum, args[1], args[2]);
2933 err_code |= ERR_ALERT | ERR_FATAL;
2934 goto out;
2935 }
2936 }
Simon Horman9dc49962015-01-30 11:22:59 +09002937 else if (!strcmp(args[1], "to")) {
2938 if (*(args[1]) == 0) {
2939 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2940 file, linenum, args[1]);
2941 err_code |= ERR_ALERT | ERR_FATAL;
2942 goto out;
2943 }
2944 free(curproxy->email_alert.to);
2945 curproxy->email_alert.to = strdup(args[2]);
2946 }
2947 else {
2948 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2949 file, linenum, args[1]);
2950 err_code |= ERR_ALERT | ERR_FATAL;
2951 goto out;
2952 }
Simon Horman64e34162015-02-06 11:11:57 +09002953 /* Indicate that the email_alert is at least partially configured */
2954 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002955 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002956 else if (!strcmp(args[0], "external-check")) {
2957 if (*(args[1]) == 0) {
2958 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2959 file, linenum, args[0]);
2960 err_code |= ERR_ALERT | ERR_FATAL;
2961 goto out;
2962 }
2963
2964 if (!strcmp(args[1], "command")) {
2965 if (*(args[1]) == 0) {
2966 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2967 file, linenum, args[1]);
2968 err_code |= ERR_ALERT | ERR_FATAL;
2969 goto out;
2970 }
2971 free(curproxy->check_command);
2972 curproxy->check_command = strdup(args[2]);
2973 }
2974 else if (!strcmp(args[1], "path")) {
2975 if (*(args[1]) == 0) {
2976 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2977 file, linenum, args[1]);
2978 err_code |= ERR_ALERT | ERR_FATAL;
2979 goto out;
2980 }
2981 free(curproxy->check_path);
2982 curproxy->check_path = strdup(args[2]);
2983 }
2984 else {
2985 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2986 file, linenum, args[1]);
2987 err_code |= ERR_ALERT | ERR_FATAL;
2988 goto out;
2989 }
2990 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002991 else if (!strcmp(args[0], "persist")) { /* persist */
2992 if (*(args[1]) == 0) {
2993 Alert("parsing [%s:%d] : missing persist method.\n",
2994 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002997 }
2998
2999 if (!strncmp(args[1], "rdp-cookie", 10)) {
3000 curproxy->options2 |= PR_O2_RDPC_PRST;
3001
Emeric Brunb982a3d2010-01-04 15:45:53 +01003002 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003003 const char *beg, *end;
3004
3005 beg = args[1] + 11;
3006 end = strchr(beg, ')');
3007
3008 if (!end || end == beg) {
3009 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3010 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003011 err_code |= ERR_ALERT | ERR_FATAL;
3012 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003013 }
3014
3015 free(curproxy->rdp_cookie_name);
3016 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3017 curproxy->rdp_cookie_len = end-beg;
3018 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003019 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003020 free(curproxy->rdp_cookie_name);
3021 curproxy->rdp_cookie_name = strdup("msts");
3022 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3023 }
3024 else { /* syntax */
3025 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3026 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003029 }
3030 }
3031 else {
3032 Alert("parsing [%s:%d] : unknown persist method.\n",
3033 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003034 err_code |= ERR_ALERT | ERR_FATAL;
3035 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003036 }
3037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003039 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003040
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003041 if (curproxy == &defproxy) {
3042 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3043 err_code |= ERR_ALERT | ERR_FATAL;
3044 goto out;
3045 }
3046
Willy Tarreau977b8e42006-12-29 14:19:17 +01003047 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003048 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003049
Willy Tarreaubaaee002006-06-26 02:48:02 +02003050 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003051 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003053 err_code |= ERR_ALERT | ERR_FATAL;
3054 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055 }
3056 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003057 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 curproxy->appsession_name = strdup(args[1]);
3059 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3060 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003061 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3062 if (err) {
3063 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3064 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003065 err_code |= ERR_ALERT | ERR_FATAL;
3066 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003067 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003068 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003069
Willy Tarreau51041c72007-09-09 21:56:53 +02003070 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003072 err_code |= ERR_ALERT | ERR_ABORT;
3073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003074 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003075
3076 cur_arg = 6;
3077 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003078 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3079 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003080 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003081 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003082 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003083 } else if (!strcmp(args[cur_arg], "prefix")) {
3084 curproxy->options2 |= PR_O2_AS_PFX;
3085 } else if (!strcmp(args[cur_arg], "mode")) {
3086 if (!*args[cur_arg + 1]) {
3087 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3088 file, linenum, args[0], args[cur_arg]);
3089 err_code |= ERR_ALERT | ERR_FATAL;
3090 goto out;
3091 }
3092
3093 cur_arg++;
3094 if (!strcmp(args[cur_arg], "query-string")) {
3095 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3096 curproxy->options2 |= PR_O2_AS_M_QS;
3097 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3098 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3099 curproxy->options2 |= PR_O2_AS_M_PP;
3100 } else {
3101 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3102 err_code |= ERR_ALERT | ERR_FATAL;
3103 goto out;
3104 }
3105 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003106 cur_arg++;
3107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003108 } /* Url App Session */
3109 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003110 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003111 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003112
Willy Tarreaubaaee002006-06-26 02:48:02 +02003113 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003114 if (curproxy == &defproxy) {
3115 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3116 err_code |= ERR_ALERT | ERR_FATAL;
3117 goto out;
3118 }
3119
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 if (*(args[4]) == 0) {
3121 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3122 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003126 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003127 curproxy->capture_name = strdup(args[2]);
3128 curproxy->capture_namelen = strlen(curproxy->capture_name);
3129 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003130 curproxy->to_log |= LW_COOKIE;
3131 }
3132 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3133 struct cap_hdr *hdr;
3134
3135 if (curproxy == &defproxy) {
3136 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 +02003137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003139 }
3140
3141 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3142 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3143 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003146 }
3147
3148 hdr = calloc(sizeof(struct cap_hdr), 1);
3149 hdr->next = curproxy->req_cap;
3150 hdr->name = strdup(args[3]);
3151 hdr->namelen = strlen(args[3]);
3152 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003153 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 hdr->index = curproxy->nb_req_cap++;
3155 curproxy->req_cap = hdr;
3156 curproxy->to_log |= LW_REQHDR;
3157 }
3158 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3159 struct cap_hdr *hdr;
3160
3161 if (curproxy == &defproxy) {
3162 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 +02003163 err_code |= ERR_ALERT | ERR_FATAL;
3164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003165 }
3166
3167 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3168 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3169 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003172 }
3173 hdr = calloc(sizeof(struct cap_hdr), 1);
3174 hdr->next = curproxy->rsp_cap;
3175 hdr->name = strdup(args[3]);
3176 hdr->namelen = strlen(args[3]);
3177 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003178 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003179 hdr->index = curproxy->nb_rsp_cap++;
3180 curproxy->rsp_cap = hdr;
3181 curproxy->to_log |= LW_RSPHDR;
3182 }
3183 else {
3184 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3185 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003186 err_code |= ERR_ALERT | ERR_FATAL;
3187 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003188 }
3189 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003191 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003192 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003193
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 if (*(args[1]) == 0) {
3195 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003197 err_code |= ERR_ALERT | ERR_FATAL;
3198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003199 }
3200 curproxy->conn_retries = atol(args[1]);
3201 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003202 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003203 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003204
3205 if (curproxy == &defproxy) {
3206 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3207 err_code |= ERR_ALERT | ERR_FATAL;
3208 goto out;
3209 }
3210
Willy Tarreau20b0de52012-12-24 15:45:22 +01003211 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3212 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3213 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3214 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003215 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003216 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3217 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 +01003218 file, linenum, args[0]);
3219 err_code |= ERR_WARN;
3220 }
3221
Willy Tarreauff011f22011-01-06 17:51:27 +01003222 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003223
Willy Tarreauff011f22011-01-06 17:51:27 +01003224 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003225 err_code |= ERR_ALERT | ERR_ABORT;
3226 goto out;
3227 }
3228
Willy Tarreau5002f572014-04-23 01:32:02 +02003229 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003230 err_code |= warnif_cond_conflicts(rule->cond,
3231 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3232 file, linenum);
3233
Willy Tarreauff011f22011-01-06 17:51:27 +01003234 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003235 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003236 else if (!strcmp(args[0], "http-response")) { /* response access control */
3237 struct http_res_rule *rule;
3238
3239 if (curproxy == &defproxy) {
3240 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3241 err_code |= ERR_ALERT | ERR_FATAL;
3242 goto out;
3243 }
3244
3245 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3246 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3247 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3248 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3249 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3250 file, linenum, args[0]);
3251 err_code |= ERR_WARN;
3252 }
3253
3254 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3255
3256 if (!rule) {
3257 err_code |= ERR_ALERT | ERR_ABORT;
3258 goto out;
3259 }
3260
3261 err_code |= warnif_cond_conflicts(rule->cond,
3262 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3263 file, linenum);
3264
3265 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3266 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003267 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3268 /* set the header name and length into the proxy structure */
3269 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3270 err_code |= ERR_WARN;
3271
3272 if (!*args[1]) {
3273 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3274 file, linenum, args[0]);
3275 err_code |= ERR_ALERT | ERR_FATAL;
3276 goto out;
3277 }
3278
3279 /* set the desired header name */
3280 free(curproxy->server_id_hdr_name);
3281 curproxy->server_id_hdr_name = strdup(args[1]);
3282 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3283 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003284 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003285 struct http_req_rule *rule;
3286
Willy Tarreaub099aca2008-10-12 17:26:37 +02003287 if (curproxy == &defproxy) {
3288 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003291 }
3292
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003293 /* emulate "block" using "http-request block". Since these rules are supposed to
3294 * be processed before all http-request rules, we put them into their own list
3295 * and will insert them at the end.
3296 */
3297 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3298 if (!rule) {
3299 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003300 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003301 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003302 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3303 err_code |= warnif_cond_conflicts(rule->cond,
3304 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3305 file, linenum);
3306 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003307
3308 if (!already_warned(WARN_BLOCK_DEPRECATED))
3309 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]);
3310
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003311 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003312 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003313 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003314
Cyril Bonté99ed3272010-01-24 23:29:44 +01003315 if (curproxy == &defproxy) {
3316 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3317 err_code |= ERR_ALERT | ERR_FATAL;
3318 goto out;
3319 }
3320
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003321 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003322 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3323 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003324 err_code |= ERR_ALERT | ERR_FATAL;
3325 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003326 }
3327
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003328 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003329 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003330 err_code |= warnif_cond_conflicts(rule->cond,
3331 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3332 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003333 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003334 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003335 struct switching_rule *rule;
3336
Willy Tarreaub099aca2008-10-12 17:26:37 +02003337 if (curproxy == &defproxy) {
3338 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003341 }
3342
Willy Tarreau55ea7572007-06-17 19:56:27 +02003343 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003345
3346 if (*(args[1]) == 0) {
3347 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003348 err_code |= ERR_ALERT | ERR_FATAL;
3349 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003350 }
3351
Willy Tarreauf51658d2014-04-23 01:21:56 +02003352 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3353 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3354 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3355 file, linenum, errmsg);
3356 err_code |= ERR_ALERT | ERR_FATAL;
3357 goto out;
3358 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003359
Willy Tarreauf51658d2014-04-23 01:21:56 +02003360 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003361 }
3362
3363 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3364 rule->cond = cond;
3365 rule->be.name = strdup(args[1]);
3366 LIST_INIT(&rule->list);
3367 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3368 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003369 else if (strcmp(args[0], "use-server") == 0) {
3370 struct server_rule *rule;
3371
3372 if (curproxy == &defproxy) {
3373 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3374 err_code |= ERR_ALERT | ERR_FATAL;
3375 goto out;
3376 }
3377
3378 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3379 err_code |= ERR_WARN;
3380
3381 if (*(args[1]) == 0) {
3382 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3383 err_code |= ERR_ALERT | ERR_FATAL;
3384 goto out;
3385 }
3386
3387 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3388 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3389 file, linenum, args[0]);
3390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
3392 }
3393
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003394 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3395 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3396 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003397 err_code |= ERR_ALERT | ERR_FATAL;
3398 goto out;
3399 }
3400
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003401 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003402
3403 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3404 rule->cond = cond;
3405 rule->srv.name = strdup(args[1]);
3406 LIST_INIT(&rule->list);
3407 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3408 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3409 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003410 else if ((!strcmp(args[0], "force-persist")) ||
3411 (!strcmp(args[0], "ignore-persist"))) {
3412 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003413
3414 if (curproxy == &defproxy) {
3415 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3416 err_code |= ERR_ALERT | ERR_FATAL;
3417 goto out;
3418 }
3419
3420 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3421 err_code |= ERR_WARN;
3422
Willy Tarreauef6494c2010-01-28 17:12:36 +01003423 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003424 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3425 file, linenum, args[0]);
3426 err_code |= ERR_ALERT | ERR_FATAL;
3427 goto out;
3428 }
3429
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003430 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3431 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3432 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003433 err_code |= ERR_ALERT | ERR_FATAL;
3434 goto out;
3435 }
3436
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003437 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3438 * where force-persist is applied.
3439 */
3440 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003441
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003442 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003443 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003444 if (!strcmp(args[0], "force-persist")) {
3445 rule->type = PERSIST_TYPE_FORCE;
3446 } else {
3447 rule->type = PERSIST_TYPE_IGNORE;
3448 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003449 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003450 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003451 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003452 else if (!strcmp(args[0], "stick-table")) {
3453 int myidx = 1;
3454
Emeric Brun32da3c42010-09-23 18:39:19 +02003455 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003456 curproxy->table.type = (unsigned int)-1;
3457 while (*args[myidx]) {
3458 const char *err;
3459
3460 if (strcmp(args[myidx], "size") == 0) {
3461 myidx++;
3462 if (!*(args[myidx])) {
3463 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3464 file, linenum, args[myidx-1]);
3465 err_code |= ERR_ALERT | ERR_FATAL;
3466 goto out;
3467 }
3468 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3469 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3470 file, linenum, *err, args[myidx-1]);
3471 err_code |= ERR_ALERT | ERR_FATAL;
3472 goto out;
3473 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003474 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003475 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003476 else if (strcmp(args[myidx], "peers") == 0) {
3477 myidx++;
Godbach50523162013-12-11 19:48:57 +08003478 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003479 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3480 file, linenum, args[myidx-1]);
3481 err_code |= ERR_ALERT | ERR_FATAL;
3482 goto out;
Godbach50523162013-12-11 19:48:57 +08003483 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003484 curproxy->table.peers.name = strdup(args[myidx++]);
3485 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003486 else if (strcmp(args[myidx], "expire") == 0) {
3487 myidx++;
3488 if (!*(args[myidx])) {
3489 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3490 file, linenum, args[myidx-1]);
3491 err_code |= ERR_ALERT | ERR_FATAL;
3492 goto out;
3493 }
3494 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3495 if (err) {
3496 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3497 file, linenum, *err, args[myidx-1]);
3498 err_code |= ERR_ALERT | ERR_FATAL;
3499 goto out;
3500 }
3501 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003502 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003503 }
3504 else if (strcmp(args[myidx], "nopurge") == 0) {
3505 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003506 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003507 }
3508 else if (strcmp(args[myidx], "type") == 0) {
3509 myidx++;
3510 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3511 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3512 file, linenum, args[myidx]);
3513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
3515 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003516 /* myidx already points to next arg */
3517 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003518 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003519 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003520 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003521
3522 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003523 nw = args[myidx];
3524 while (*nw) {
3525 /* the "store" keyword supports a comma-separated list */
3526 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003527 sa = NULL; /* store arg */
3528 while (*nw && *nw != ',') {
3529 if (*nw == '(') {
3530 *nw = 0;
3531 sa = ++nw;
3532 while (*nw != ')') {
3533 if (!*nw) {
3534 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3535 file, linenum, args[0], cw);
3536 err_code |= ERR_ALERT | ERR_FATAL;
3537 goto out;
3538 }
3539 nw++;
3540 }
3541 *nw = '\0';
3542 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003543 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003544 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003545 if (*nw)
3546 *nw++ = '\0';
3547 type = stktable_get_data_type(cw);
3548 if (type < 0) {
3549 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3550 file, linenum, args[0], cw);
3551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
3553 }
Willy Tarreauac782882010-06-20 10:41:54 +02003554
3555 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3556 switch (err) {
3557 case PE_NONE: break;
3558 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003559 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3560 file, linenum, args[0], cw);
3561 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003562 break;
3563
3564 case PE_ARG_MISSING:
3565 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3566 file, linenum, args[0], cw);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569
3570 case PE_ARG_NOT_USED:
3571 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3572 file, linenum, args[0], cw);
3573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
3575
3576 default:
3577 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3578 file, linenum, args[0], cw);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003581 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003582 }
3583 myidx++;
3584 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003585 else {
3586 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3587 file, linenum, args[myidx]);
3588 err_code |= ERR_ALERT | ERR_FATAL;
3589 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003590 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003591 }
3592
3593 if (!curproxy->table.size) {
3594 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3595 file, linenum);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599
3600 if (curproxy->table.type == (unsigned int)-1) {
3601 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3602 file, linenum);
3603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
3605 }
3606 }
3607 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003608 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003609 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003610 int myidx = 0;
3611 const char *name = NULL;
3612 int flags;
3613
3614 if (curproxy == &defproxy) {
3615 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
3618 }
3619
3620 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3621 err_code |= ERR_WARN;
3622 goto out;
3623 }
3624
3625 myidx++;
3626 if ((strcmp(args[myidx], "store") == 0) ||
3627 (strcmp(args[myidx], "store-request") == 0)) {
3628 myidx++;
3629 flags = STK_IS_STORE;
3630 }
3631 else if (strcmp(args[myidx], "store-response") == 0) {
3632 myidx++;
3633 flags = STK_IS_STORE | STK_ON_RSP;
3634 }
3635 else if (strcmp(args[myidx], "match") == 0) {
3636 myidx++;
3637 flags = STK_IS_MATCH;
3638 }
3639 else if (strcmp(args[myidx], "on") == 0) {
3640 myidx++;
3641 flags = STK_IS_MATCH | STK_IS_STORE;
3642 }
3643 else {
3644 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
3647 }
3648
3649 if (*(args[myidx]) == 0) {
3650 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
3653 }
3654
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003655 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003656 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003657 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003658 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
3661 }
3662
3663 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003664 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3665 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3666 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003667 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003668 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003669 goto out;
3670 }
3671 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003672 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3673 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\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 }
3680
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003681 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003682 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003683
Emeric Brunb982a3d2010-01-04 15:45:53 +01003684 if (strcmp(args[myidx], "table") == 0) {
3685 myidx++;
3686 name = args[myidx++];
3687 }
3688
Willy Tarreauef6494c2010-01-28 17:12:36 +01003689 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003690 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3691 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3692 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003693 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003694 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003695 goto out;
3696 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003697 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003698 else if (*(args[myidx])) {
3699 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3700 file, linenum, args[0], args[myidx]);
3701 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003702 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003703 goto out;
3704 }
Emeric Brun97679e72010-09-23 17:56:44 +02003705 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003706 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003707 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003708 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003709
Emeric Brunb982a3d2010-01-04 15:45:53 +01003710 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3711 rule->cond = cond;
3712 rule->expr = expr;
3713 rule->flags = flags;
3714 rule->table.name = name ? strdup(name) : NULL;
3715 LIST_INIT(&rule->list);
3716 if (flags & STK_ON_RSP)
3717 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3718 else
3719 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3720 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 else if (!strcmp(args[0], "stats")) {
3722 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3723 curproxy->uri_auth = NULL; /* we must detach from the default config */
3724
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003725 if (!*args[1]) {
3726 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003727 } else if (!strcmp(args[1], "admin")) {
3728 struct stats_admin_rule *rule;
3729
3730 if (curproxy == &defproxy) {
3731 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3732 err_code |= ERR_ALERT | ERR_FATAL;
3733 goto out;
3734 }
3735
3736 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3737 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3738 err_code |= ERR_ALERT | ERR_ABORT;
3739 goto out;
3740 }
3741
3742 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3743 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3744 file, linenum, args[0], args[1]);
3745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
3747 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003748 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3749 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3750 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003751 err_code |= ERR_ALERT | ERR_FATAL;
3752 goto out;
3753 }
3754
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003755 err_code |= warnif_cond_conflicts(cond,
3756 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3757 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003758
3759 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3760 rule->cond = cond;
3761 LIST_INIT(&rule->list);
3762 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003763 } else if (!strcmp(args[1], "uri")) {
3764 if (*(args[2]) == 0) {
3765 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003768 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3769 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_ABORT;
3771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 }
3773 } else if (!strcmp(args[1], "realm")) {
3774 if (*(args[2]) == 0) {
3775 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003776 err_code |= ERR_ALERT | ERR_FATAL;
3777 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003778 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3779 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003780 err_code |= ERR_ALERT | ERR_ABORT;
3781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003782 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003783 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003784 unsigned interval;
3785
3786 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3787 if (err) {
3788 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3789 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003790 err_code |= ERR_ALERT | ERR_FATAL;
3791 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003792 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3793 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003794 err_code |= ERR_ALERT | ERR_ABORT;
3795 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003796 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003797 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003798 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003799
3800 if (curproxy == &defproxy) {
3801 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3802 err_code |= ERR_ALERT | ERR_FATAL;
3803 goto out;
3804 }
3805
3806 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3807 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3808 err_code |= ERR_ALERT | ERR_ABORT;
3809 goto out;
3810 }
3811
Willy Tarreauff011f22011-01-06 17:51:27 +01003812 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3813 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003814 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3815 file, linenum, args[0]);
3816 err_code |= ERR_WARN;
3817 }
3818
Willy Tarreauff011f22011-01-06 17:51:27 +01003819 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003820
Willy Tarreauff011f22011-01-06 17:51:27 +01003821 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003822 err_code |= ERR_ALERT | ERR_ABORT;
3823 goto out;
3824 }
3825
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003826 err_code |= warnif_cond_conflicts(rule->cond,
3827 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3828 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003829 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003830
Willy Tarreaubaaee002006-06-26 02:48:02 +02003831 } else if (!strcmp(args[1], "auth")) {
3832 if (*(args[2]) == 0) {
3833 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003834 err_code |= ERR_ALERT | ERR_FATAL;
3835 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3837 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_ALERT | ERR_ABORT;
3839 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003840 }
3841 } else if (!strcmp(args[1], "scope")) {
3842 if (*(args[2]) == 0) {
3843 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003846 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3847 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003848 err_code |= ERR_ALERT | ERR_ABORT;
3849 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003850 }
3851 } else if (!strcmp(args[1], "enable")) {
3852 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3853 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003854 err_code |= ERR_ALERT | ERR_ABORT;
3855 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003856 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003857 } else if (!strcmp(args[1], "hide-version")) {
3858 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3859 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003860 err_code |= ERR_ALERT | ERR_ABORT;
3861 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003862 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003863 } else if (!strcmp(args[1], "show-legends")) {
3864 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3865 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3866 err_code |= ERR_ALERT | ERR_ABORT;
3867 goto out;
3868 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003869 } else if (!strcmp(args[1], "show-node")) {
3870
3871 if (*args[2]) {
3872 int i;
3873 char c;
3874
3875 for (i=0; args[2][i]; i++) {
3876 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003877 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3878 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003879 break;
3880 }
3881
3882 if (!i || args[2][i]) {
3883 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3884 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3885 file, linenum, args[0], args[1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
3889 }
3890
3891 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3892 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3893 err_code |= ERR_ALERT | ERR_ABORT;
3894 goto out;
3895 }
3896 } else if (!strcmp(args[1], "show-desc")) {
3897 char *desc = NULL;
3898
3899 if (*args[2]) {
3900 int i, len=0;
3901 char *d;
3902
Willy Tarreau348acfe2014-04-14 15:00:39 +02003903 for (i = 2; *args[i]; i++)
3904 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003905
3906 desc = d = (char *)calloc(1, len);
3907
Willy Tarreau348acfe2014-04-14 15:00:39 +02003908 d += snprintf(d, desc + len - d, "%s", args[2]);
3909 for (i = 3; *args[i]; i++)
3910 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003911 }
3912
3913 if (!*args[2] && !global.desc)
3914 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3915 file, linenum, args[1]);
3916 else {
3917 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3918 free(desc);
3919 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3920 err_code |= ERR_ALERT | ERR_ABORT;
3921 goto out;
3922 }
3923 free(desc);
3924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003925 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003926stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003927 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 +01003928 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003929 err_code |= ERR_ALERT | ERR_FATAL;
3930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003931 }
3932 }
3933 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003934 int optnum;
3935
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003936 if (*(args[1]) == '\0') {
3937 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3938 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003939 err_code |= ERR_ALERT | ERR_FATAL;
3940 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003941 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003942
3943 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3944 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003945 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3946 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3947 file, linenum, cfg_opts[optnum].name);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
Willy Tarreau93893792009-07-23 13:19:11 +02003951 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3952 err_code |= ERR_WARN;
3953 goto out;
3954 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003955
Willy Tarreau3842f002009-06-14 11:39:52 +02003956 curproxy->no_options &= ~cfg_opts[optnum].val;
3957 curproxy->options &= ~cfg_opts[optnum].val;
3958
3959 switch (kwm) {
3960 case KWM_STD:
3961 curproxy->options |= cfg_opts[optnum].val;
3962 break;
3963 case KWM_NO:
3964 curproxy->no_options |= cfg_opts[optnum].val;
3965 break;
3966 case KWM_DEF: /* already cleared */
3967 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003968 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003969
Willy Tarreau93893792009-07-23 13:19:11 +02003970 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003971 }
3972 }
3973
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003974 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3975 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003976 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3977 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3978 file, linenum, cfg_opts2[optnum].name);
3979 err_code |= ERR_ALERT | ERR_FATAL;
3980 goto out;
3981 }
Willy Tarreau93893792009-07-23 13:19:11 +02003982 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3983 err_code |= ERR_WARN;
3984 goto out;
3985 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003986
Willy Tarreau3842f002009-06-14 11:39:52 +02003987 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3988 curproxy->options2 &= ~cfg_opts2[optnum].val;
3989
3990 switch (kwm) {
3991 case KWM_STD:
3992 curproxy->options2 |= cfg_opts2[optnum].val;
3993 break;
3994 case KWM_NO:
3995 curproxy->no_options2 |= cfg_opts2[optnum].val;
3996 break;
3997 case KWM_DEF: /* already cleared */
3998 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003999 }
Willy Tarreau93893792009-07-23 13:19:11 +02004000 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004001 }
4002 }
4003
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004004 /* HTTP options override each other. They can be cancelled using
4005 * "no option xxx" which only switches to default mode if the mode
4006 * was this one (useful for cancelling options set in defaults
4007 * sections).
4008 */
4009 if (strcmp(args[1], "httpclose") == 0) {
4010 if (kwm == KWM_STD) {
4011 curproxy->options &= ~PR_O_HTTP_MODE;
4012 curproxy->options |= PR_O_HTTP_PCL;
4013 goto out;
4014 }
4015 else if (kwm == KWM_NO) {
4016 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4017 curproxy->options &= ~PR_O_HTTP_MODE;
4018 goto out;
4019 }
4020 }
4021 else if (strcmp(args[1], "forceclose") == 0) {
4022 if (kwm == KWM_STD) {
4023 curproxy->options &= ~PR_O_HTTP_MODE;
4024 curproxy->options |= PR_O_HTTP_FCL;
4025 goto out;
4026 }
4027 else if (kwm == KWM_NO) {
4028 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4029 curproxy->options &= ~PR_O_HTTP_MODE;
4030 goto out;
4031 }
4032 }
4033 else if (strcmp(args[1], "http-server-close") == 0) {
4034 if (kwm == KWM_STD) {
4035 curproxy->options &= ~PR_O_HTTP_MODE;
4036 curproxy->options |= PR_O_HTTP_SCL;
4037 goto out;
4038 }
4039 else if (kwm == KWM_NO) {
4040 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4041 curproxy->options &= ~PR_O_HTTP_MODE;
4042 goto out;
4043 }
4044 }
4045 else if (strcmp(args[1], "http-keep-alive") == 0) {
4046 if (kwm == KWM_STD) {
4047 curproxy->options &= ~PR_O_HTTP_MODE;
4048 curproxy->options |= PR_O_HTTP_KAL;
4049 goto out;
4050 }
4051 else if (kwm == KWM_NO) {
4052 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4053 curproxy->options &= ~PR_O_HTTP_MODE;
4054 goto out;
4055 }
4056 }
4057 else if (strcmp(args[1], "http-tunnel") == 0) {
4058 if (kwm == KWM_STD) {
4059 curproxy->options &= ~PR_O_HTTP_MODE;
4060 curproxy->options |= PR_O_HTTP_TUN;
4061 goto out;
4062 }
4063 else if (kwm == KWM_NO) {
4064 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4065 curproxy->options &= ~PR_O_HTTP_MODE;
4066 goto out;
4067 }
4068 }
4069
Willy Tarreau3842f002009-06-14 11:39:52 +02004070 if (kwm != KWM_STD) {
4071 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004072 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004075 }
4076
Emeric Brun3a058f32009-06-30 18:26:00 +02004077 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004078 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004079 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004080 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004081 if (*(args[2]) != '\0') {
4082 if (!strcmp(args[2], "clf")) {
4083 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004084 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004085 } else {
4086 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004087 err_code |= ERR_ALERT | ERR_FATAL;
4088 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004089 }
4090 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004091 if (curproxy->conf.logformat_string != default_http_log_format &&
4092 curproxy->conf.logformat_string != default_tcp_log_format &&
4093 curproxy->conf.logformat_string != clf_http_log_format)
4094 free(curproxy->conf.logformat_string);
4095 curproxy->conf.logformat_string = logformat;
4096
4097 free(curproxy->conf.lfs_file);
4098 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4099 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004100 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004101 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004103 if (curproxy->conf.logformat_string != default_http_log_format &&
4104 curproxy->conf.logformat_string != default_tcp_log_format &&
4105 curproxy->conf.logformat_string != clf_http_log_format)
4106 free(curproxy->conf.logformat_string);
4107 curproxy->conf.logformat_string = default_tcp_log_format;
4108
4109 free(curproxy->conf.lfs_file);
4110 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4111 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004113 else if (!strcmp(args[1], "tcpka")) {
4114 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004115 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004116 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004117
4118 if (curproxy->cap & PR_CAP_FE)
4119 curproxy->options |= PR_O_TCP_CLI_KA;
4120 if (curproxy->cap & PR_CAP_BE)
4121 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004122 }
4123 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004124 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004125 err_code |= ERR_WARN;
4126
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004128 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004129 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004130 curproxy->options2 &= ~PR_O2_CHK_ANY;
4131 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004132 if (!*args[2]) { /* no argument */
4133 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4134 curproxy->check_len = strlen(DEF_CHECK_REQ);
4135 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004136 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004137 curproxy->check_req = (char *)malloc(reqlen);
4138 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004139 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004140 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004141 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004142 if (*args[4])
4143 reqlen += strlen(args[4]);
4144 else
4145 reqlen += strlen("HTTP/1.0");
4146
4147 curproxy->check_req = (char *)malloc(reqlen);
4148 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004149 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004150 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004151 }
4152 else if (!strcmp(args[1], "ssl-hello-chk")) {
4153 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004154 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004155 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004156
Willy Tarreaua534fea2008-08-03 12:19:50 +02004157 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004158 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004159 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004160 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004161 }
Willy Tarreau23677902007-05-08 23:50:35 +02004162 else if (!strcmp(args[1], "smtpchk")) {
4163 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004164 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004165 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004166 curproxy->options2 &= ~PR_O2_CHK_ANY;
4167 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004168
4169 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4170 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4171 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4172 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4173 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4174 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4175 curproxy->check_req = (char *)malloc(reqlen);
4176 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4177 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4178 } else {
4179 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4180 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4181 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4182 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4183 }
4184 }
4185 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004186 else if (!strcmp(args[1], "pgsql-check")) {
4187 /* use PostgreSQL request to check servers' health */
4188 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4189 err_code |= ERR_WARN;
4190
4191 free(curproxy->check_req);
4192 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004193 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004194 curproxy->options2 |= PR_O2_PGSQL_CHK;
4195
4196 if (*(args[2])) {
4197 int cur_arg = 2;
4198
4199 while (*(args[cur_arg])) {
4200 if (strcmp(args[cur_arg], "user") == 0) {
4201 char * packet;
4202 uint32_t packet_len;
4203 uint32_t pv;
4204
4205 /* suboption header - needs additional argument for it */
4206 if (*(args[cur_arg+1]) == 0) {
4207 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4208 file, linenum, args[0], args[1], args[cur_arg]);
4209 err_code |= ERR_ALERT | ERR_FATAL;
4210 goto out;
4211 }
4212
4213 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4214 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4215 pv = htonl(0x30000); /* protocol version 3.0 */
4216
4217 packet = (char*) calloc(1, packet_len);
4218
4219 memcpy(packet + 4, &pv, 4);
4220
4221 /* copy "user" */
4222 memcpy(packet + 8, "user", 4);
4223
4224 /* copy username */
4225 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4226
4227 free(curproxy->check_req);
4228 curproxy->check_req = packet;
4229 curproxy->check_len = packet_len;
4230
4231 packet_len = htonl(packet_len);
4232 memcpy(packet, &packet_len, 4);
4233 cur_arg += 2;
4234 } else {
4235 /* unknown suboption - catchall */
4236 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4237 file, linenum, args[0], args[1]);
4238 err_code |= ERR_ALERT | ERR_FATAL;
4239 goto out;
4240 }
4241 } /* end while loop */
4242 }
4243 }
4244
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004245 else if (!strcmp(args[1], "redis-check")) {
4246 /* use REDIS PING request to check servers' health */
4247 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4248 err_code |= ERR_WARN;
4249
4250 free(curproxy->check_req);
4251 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004252 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004253 curproxy->options2 |= PR_O2_REDIS_CHK;
4254
4255 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4256 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4257 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4258 }
4259
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004260 else if (!strcmp(args[1], "mysql-check")) {
4261 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004262 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4263 err_code |= ERR_WARN;
4264
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004265 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004266 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004267 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004268 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004269
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004270 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004271 * const char mysql40_client_auth_pkt[] = {
4272 * "\x0e\x00\x00" // packet length
4273 * "\x01" // packet number
4274 * "\x00\x00" // client capabilities
4275 * "\x00\x00\x01" // max packet
4276 * "haproxy\x00" // username (null terminated string)
4277 * "\x00" // filler (always 0x00)
4278 * "\x01\x00\x00" // packet length
4279 * "\x00" // packet number
4280 * "\x01" // COM_QUIT command
4281 * };
4282 */
4283
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004284 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4285 * const char mysql41_client_auth_pkt[] = {
4286 * "\x0e\x00\x00\" // packet length
4287 * "\x01" // packet number
4288 * "\x00\x00\x00\x00" // client capabilities
4289 * "\x00\x00\x00\x01" // max packet
4290 * "\x21" // character set (UTF-8)
4291 * char[23] // All zeroes
4292 * "haproxy\x00" // username (null terminated string)
4293 * "\x00" // filler (always 0x00)
4294 * "\x01\x00\x00" // packet length
4295 * "\x00" // packet number
4296 * "\x01" // COM_QUIT command
4297 * };
4298 */
4299
4300
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004301 if (*(args[2])) {
4302 int cur_arg = 2;
4303
4304 while (*(args[cur_arg])) {
4305 if (strcmp(args[cur_arg], "user") == 0) {
4306 char *mysqluser;
4307 int packetlen, reqlen, userlen;
4308
4309 /* suboption header - needs additional argument for it */
4310 if (*(args[cur_arg+1]) == 0) {
4311 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4312 file, linenum, args[0], args[1], args[cur_arg]);
4313 err_code |= ERR_ALERT | ERR_FATAL;
4314 goto out;
4315 }
4316 mysqluser = args[cur_arg + 1];
4317 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004318
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004319 if (*(args[cur_arg+2])) {
4320 if (!strcmp(args[cur_arg+2], "post-41")) {
4321 packetlen = userlen + 7 + 27;
4322 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004323
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004324 free(curproxy->check_req);
4325 curproxy->check_req = (char *)calloc(1, reqlen);
4326 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004327
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004328 snprintf(curproxy->check_req, 4, "%c%c%c",
4329 ((unsigned char) packetlen & 0xff),
4330 ((unsigned char) (packetlen >> 8) & 0xff),
4331 ((unsigned char) (packetlen >> 16) & 0xff));
4332
4333 curproxy->check_req[3] = 1;
4334 curproxy->check_req[5] = 130;
4335 curproxy->check_req[11] = 1;
4336 curproxy->check_req[12] = 33;
4337 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4338 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4339 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4340 cur_arg += 3;
4341 } else {
4342 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346 } else {
4347 packetlen = userlen + 7;
4348 reqlen = packetlen + 9;
4349
4350 free(curproxy->check_req);
4351 curproxy->check_req = (char *)calloc(1, reqlen);
4352 curproxy->check_len = reqlen;
4353
4354 snprintf(curproxy->check_req, 4, "%c%c%c",
4355 ((unsigned char) packetlen & 0xff),
4356 ((unsigned char) (packetlen >> 8) & 0xff),
4357 ((unsigned char) (packetlen >> 16) & 0xff));
4358
4359 curproxy->check_req[3] = 1;
4360 curproxy->check_req[5] = 128;
4361 curproxy->check_req[8] = 1;
4362 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4363 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4364 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4365 cur_arg += 2;
4366 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004367 } else {
4368 /* unknown suboption - catchall */
4369 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4370 file, linenum, args[0], args[1]);
4371 err_code |= ERR_ALERT | ERR_FATAL;
4372 goto out;
4373 }
4374 } /* end while loop */
4375 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004376 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004377 else if (!strcmp(args[1], "ldap-check")) {
4378 /* use LDAP request to check servers' health */
4379 free(curproxy->check_req);
4380 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004381 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004382 curproxy->options2 |= PR_O2_LDAP_CHK;
4383
4384 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4385 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4386 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4387 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004388 else if (!strcmp(args[1], "tcp-check")) {
4389 /* use raw TCPCHK send/expect to check servers' health */
4390 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4391 err_code |= ERR_WARN;
4392
4393 free(curproxy->check_req);
4394 curproxy->check_req = NULL;
4395 curproxy->options2 &= ~PR_O2_CHK_ANY;
4396 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4397 }
Simon Horman98637e52014-06-20 12:30:16 +09004398 else if (!strcmp(args[1], "external-check")) {
4399 /* excute an external command to check servers' health */
4400 free(curproxy->check_req);
4401 curproxy->check_req = NULL;
4402 curproxy->options2 &= ~PR_O2_CHK_ANY;
4403 curproxy->options2 |= PR_O2_EXT_CHK;
4404 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004405 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004406 int cur_arg;
4407
4408 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4409 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004410 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004411
Willy Tarreau87cf5142011-08-19 22:57:24 +02004412 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004413
4414 free(curproxy->fwdfor_hdr_name);
4415 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4416 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4417
4418 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4419 cur_arg = 2;
4420 while (*(args[cur_arg])) {
4421 if (!strcmp(args[cur_arg], "except")) {
4422 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004423 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004424 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4425 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004426 err_code |= ERR_ALERT | ERR_FATAL;
4427 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004428 }
4429 /* flush useless bits */
4430 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004431 cur_arg += 2;
4432 } else if (!strcmp(args[cur_arg], "header")) {
4433 /* suboption header - needs additional argument for it */
4434 if (*(args[cur_arg+1]) == 0) {
4435 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4436 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004437 err_code |= ERR_ALERT | ERR_FATAL;
4438 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004439 }
4440 free(curproxy->fwdfor_hdr_name);
4441 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4442 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4443 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004444 } else if (!strcmp(args[cur_arg], "if-none")) {
4445 curproxy->options &= ~PR_O_FF_ALWAYS;
4446 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004447 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004448 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004449 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004450 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004451 err_code |= ERR_ALERT | ERR_FATAL;
4452 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004453 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004454 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004455 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004456 else if (!strcmp(args[1], "originalto")) {
4457 int cur_arg;
4458
4459 /* insert x-original-to field, but not for the IP address listed as an except.
4460 * set default options (ie: bitfield, header name, etc)
4461 */
4462
4463 curproxy->options |= PR_O_ORGTO;
4464
4465 free(curproxy->orgto_hdr_name);
4466 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4467 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4468
Willy Tarreau87cf5142011-08-19 22:57:24 +02004469 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004470 cur_arg = 2;
4471 while (*(args[cur_arg])) {
4472 if (!strcmp(args[cur_arg], "except")) {
4473 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004474 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 +02004475 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4476 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004477 err_code |= ERR_ALERT | ERR_FATAL;
4478 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004479 }
4480 /* flush useless bits */
4481 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4482 cur_arg += 2;
4483 } else if (!strcmp(args[cur_arg], "header")) {
4484 /* suboption header - needs additional argument for it */
4485 if (*(args[cur_arg+1]) == 0) {
4486 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4487 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004488 err_code |= ERR_ALERT | ERR_FATAL;
4489 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004490 }
4491 free(curproxy->orgto_hdr_name);
4492 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4493 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4494 cur_arg += 2;
4495 } else {
4496 /* unknown suboption - catchall */
4497 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4498 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004499 err_code |= ERR_ALERT | ERR_FATAL;
4500 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004501 }
4502 } /* end while loop */
4503 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 else {
4505 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004506 err_code |= ERR_ALERT | ERR_FATAL;
4507 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004508 }
Willy Tarreau93893792009-07-23 13:19:11 +02004509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004511 else if (!strcmp(args[0], "default_backend")) {
4512 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004513 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004514
4515 if (*(args[1]) == 0) {
4516 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004517 err_code |= ERR_ALERT | ERR_FATAL;
4518 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004519 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004520 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004521 curproxy->defbe.name = strdup(args[1]);
4522 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004523 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004524 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004525 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004526
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004527 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4528 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 +01004529 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004530 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004531 /* enable reconnections to dispatch */
4532 curproxy->options |= PR_O_REDISP;
4533 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004534 else if (!strcmp(args[0], "http-check")) {
4535 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004536 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004537
4538 if (strcmp(args[1], "disable-on-404") == 0) {
4539 /* enable a graceful server shutdown on an HTTP 404 response */
4540 curproxy->options |= PR_O_DISABLE404;
4541 }
Willy Tarreauef781042010-01-27 11:53:01 +01004542 else if (strcmp(args[1], "send-state") == 0) {
4543 /* enable emission of the apparent state of a server in HTTP checks */
4544 curproxy->options2 |= PR_O2_CHK_SNDST;
4545 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004546 else if (strcmp(args[1], "expect") == 0) {
4547 const char *ptr_arg;
4548 int cur_arg;
4549
4550 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4551 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4552 err_code |= ERR_ALERT | ERR_FATAL;
4553 goto out;
4554 }
4555
4556 cur_arg = 2;
4557 /* consider exclamation marks, sole or at the beginning of a word */
4558 while (*(ptr_arg = args[cur_arg])) {
4559 while (*ptr_arg == '!') {
4560 curproxy->options2 ^= PR_O2_EXP_INV;
4561 ptr_arg++;
4562 }
4563 if (*ptr_arg)
4564 break;
4565 cur_arg++;
4566 }
4567 /* now ptr_arg points to the beginning of a word past any possible
4568 * exclamation mark, and cur_arg is the argument which holds this word.
4569 */
4570 if (strcmp(ptr_arg, "status") == 0) {
4571 if (!*(args[cur_arg + 1])) {
4572 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4573 file, linenum, args[0], args[1], ptr_arg);
4574 err_code |= ERR_ALERT | ERR_FATAL;
4575 goto out;
4576 }
4577 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004578 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004579 curproxy->expect_str = strdup(args[cur_arg + 1]);
4580 }
4581 else if (strcmp(ptr_arg, "string") == 0) {
4582 if (!*(args[cur_arg + 1])) {
4583 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4584 file, linenum, args[0], args[1], ptr_arg);
4585 err_code |= ERR_ALERT | ERR_FATAL;
4586 goto out;
4587 }
4588 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004589 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004590 curproxy->expect_str = strdup(args[cur_arg + 1]);
4591 }
4592 else if (strcmp(ptr_arg, "rstatus") == 0) {
4593 if (!*(args[cur_arg + 1])) {
4594 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4595 file, linenum, args[0], args[1], ptr_arg);
4596 err_code |= ERR_ALERT | ERR_FATAL;
4597 goto out;
4598 }
4599 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004600 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004601 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004602 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004603 free(curproxy->expect_regex);
4604 curproxy->expect_regex = NULL;
4605 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004606 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004607 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4608 error = NULL;
4609 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4610 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4611 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4612 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004613 err_code |= ERR_ALERT | ERR_FATAL;
4614 goto out;
4615 }
4616 }
4617 else if (strcmp(ptr_arg, "rstring") == 0) {
4618 if (!*(args[cur_arg + 1])) {
4619 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4620 file, linenum, args[0], args[1], ptr_arg);
4621 err_code |= ERR_ALERT | ERR_FATAL;
4622 goto out;
4623 }
4624 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004625 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004626 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004627 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004628 free(curproxy->expect_regex);
4629 curproxy->expect_regex = NULL;
4630 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004631 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004632 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4633 error = NULL;
4634 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4635 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4636 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4637 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004638 err_code |= ERR_ALERT | ERR_FATAL;
4639 goto out;
4640 }
4641 }
4642 else {
4643 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4644 file, linenum, args[0], args[1], ptr_arg);
4645 err_code |= ERR_ALERT | ERR_FATAL;
4646 goto out;
4647 }
4648 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004649 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004650 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 +02004651 err_code |= ERR_ALERT | ERR_FATAL;
4652 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004653 }
4654 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004655 else if (!strcmp(args[0], "tcp-check")) {
4656 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4657 err_code |= ERR_WARN;
4658
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004659 if (strcmp(args[1], "connect") == 0) {
4660 const char *ptr_arg;
4661 int cur_arg;
4662 struct tcpcheck_rule *tcpcheck;
4663 struct list *l;
4664
4665 /* check if first rule is also a 'connect' action */
4666 l = (struct list *)&curproxy->tcpcheck_rules;
4667 if (l->p != l->n) {
4668 tcpcheck = (struct tcpcheck_rule *)l->n;
4669 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4670 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4671 file, linenum);
4672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
4674 }
4675 }
4676
4677 cur_arg = 2;
4678 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4679 tcpcheck->action = TCPCHK_ACT_CONNECT;
4680
4681 /* parsing each parameters to fill up the rule */
4682 while (*(ptr_arg = args[cur_arg])) {
4683 /* tcp port */
4684 if (strcmp(args[cur_arg], "port") == 0) {
4685 if ( (atol(args[cur_arg + 1]) > 65535) ||
4686 (atol(args[cur_arg + 1]) < 1) ){
4687 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4688 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4689 err_code |= ERR_ALERT | ERR_FATAL;
4690 goto out;
4691 }
4692 tcpcheck->port = atol(args[cur_arg + 1]);
4693 cur_arg += 2;
4694 }
4695 /* send proxy protocol */
4696 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4697 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4698 cur_arg++;
4699 }
4700#ifdef USE_OPENSSL
4701 else if (strcmp(args[cur_arg], "ssl") == 0) {
4702 curproxy->options |= PR_O_TCPCHK_SSL;
4703 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4704 cur_arg++;
4705 }
4706#endif /* USE_OPENSSL */
4707 else {
4708#ifdef USE_OPENSSL
4709 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4710#else /* USE_OPENSSL */
4711 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4712#endif /* USE_OPENSSL */
4713 file, linenum, args[0], args[1], args[cur_arg]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
4717
4718 }
4719
4720 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4721 }
4722 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004723 if (! *(args[2]) ) {
4724 /* SEND string expected */
4725 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4726 file, linenum, args[0], args[1], args[2]);
4727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729 } else {
4730 struct tcpcheck_rule *tcpcheck;
4731
4732 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4733
4734 tcpcheck->action = TCPCHK_ACT_SEND;
4735 tcpcheck->string_len = strlen(args[2]);
4736 tcpcheck->string = strdup(args[2]);
4737 tcpcheck->expect_regex = NULL;
4738
4739 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4740 }
4741 }
4742 else if (strcmp(args[1], "send-binary") == 0) {
4743 if (! *(args[2]) ) {
4744 /* SEND binary string expected */
4745 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4746 file, linenum, args[0], args[1], args[2]);
4747 err_code |= ERR_ALERT | ERR_FATAL;
4748 goto out;
4749 } else {
4750 struct tcpcheck_rule *tcpcheck;
4751 char *err = NULL;
4752
4753 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4754
4755 tcpcheck->action = TCPCHK_ACT_SEND;
4756 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4757 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4758 file, linenum, args[0], args[1], args[2], err);
4759 err_code |= ERR_ALERT | ERR_FATAL;
4760 goto out;
4761 }
4762 tcpcheck->expect_regex = NULL;
4763
4764 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4765 }
4766 }
4767 else if (strcmp(args[1], "expect") == 0) {
4768 const char *ptr_arg;
4769 int cur_arg;
4770 int inverse = 0;
4771
4772 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4773 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4774 err_code |= ERR_ALERT | ERR_FATAL;
4775 goto out;
4776 }
4777
4778 cur_arg = 2;
4779 /* consider exclamation marks, sole or at the beginning of a word */
4780 while (*(ptr_arg = args[cur_arg])) {
4781 while (*ptr_arg == '!') {
4782 inverse = !inverse;
4783 ptr_arg++;
4784 }
4785 if (*ptr_arg)
4786 break;
4787 cur_arg++;
4788 }
4789 /* now ptr_arg points to the beginning of a word past any possible
4790 * exclamation mark, and cur_arg is the argument which holds this word.
4791 */
4792 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004793 struct tcpcheck_rule *tcpcheck;
4794 char *err = NULL;
4795
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004796 if (!*(args[cur_arg + 1])) {
4797 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4798 file, linenum, args[0], args[1], ptr_arg);
4799 err_code |= ERR_ALERT | ERR_FATAL;
4800 goto out;
4801 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004802
4803 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4804
4805 tcpcheck->action = TCPCHK_ACT_EXPECT;
4806 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4807 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4808 file, linenum, args[0], args[1], args[2], err);
4809 err_code |= ERR_ALERT | ERR_FATAL;
4810 goto out;
4811 }
4812 tcpcheck->expect_regex = NULL;
4813 tcpcheck->inverse = inverse;
4814
4815 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4816 }
4817 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004818 struct tcpcheck_rule *tcpcheck;
4819
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004820 if (!*(args[cur_arg + 1])) {
4821 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4822 file, linenum, args[0], args[1], ptr_arg);
4823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004826
4827 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4828
4829 tcpcheck->action = TCPCHK_ACT_EXPECT;
4830 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4831 tcpcheck->string = strdup(args[cur_arg + 1]);
4832 tcpcheck->expect_regex = NULL;
4833 tcpcheck->inverse = inverse;
4834
4835 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4836 }
4837 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004838 struct tcpcheck_rule *tcpcheck;
4839
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004840 if (!*(args[cur_arg + 1])) {
4841 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4842 file, linenum, args[0], args[1], ptr_arg);
4843 err_code |= ERR_ALERT | ERR_FATAL;
4844 goto out;
4845 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004846
4847 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4848
4849 tcpcheck->action = TCPCHK_ACT_EXPECT;
4850 tcpcheck->string_len = 0;
4851 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004852 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4853 error = NULL;
4854 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4855 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4856 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4857 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
4860 }
4861 tcpcheck->inverse = inverse;
4862
4863 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4864 }
4865 else {
4866 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4867 file, linenum, args[0], args[1], ptr_arg);
4868 err_code |= ERR_ALERT | ERR_FATAL;
4869 goto out;
4870 }
4871 }
4872 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004873 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004874 err_code |= ERR_ALERT | ERR_FATAL;
4875 goto out;
4876 }
4877 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004878 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004879 if (curproxy == &defproxy) {
4880 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004881 err_code |= ERR_ALERT | ERR_FATAL;
4882 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004883 }
4884
Willy Tarreaub80c2302007-11-30 20:51:32 +01004885 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004886 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004887
4888 if (strcmp(args[1], "fail") == 0) {
4889 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004890 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004891 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4892 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004893 err_code |= ERR_ALERT | ERR_FATAL;
4894 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004895 }
4896
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004897 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4898 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4899 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004900 err_code |= ERR_ALERT | ERR_FATAL;
4901 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004902 }
4903 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4904 }
4905 else {
4906 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004907 err_code |= ERR_ALERT | ERR_FATAL;
4908 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004909 }
4910 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004911#ifdef TPROXY
4912 else if (!strcmp(args[0], "transparent")) {
4913 /* enable transparent proxy connections */
4914 curproxy->options |= PR_O_TRANSP;
4915 }
4916#endif
4917 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004918 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004919 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004920
Willy Tarreaubaaee002006-06-26 02:48:02 +02004921 if (*(args[1]) == 0) {
4922 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004923 err_code |= ERR_ALERT | ERR_FATAL;
4924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 }
4926 curproxy->maxconn = atol(args[1]);
4927 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004928 else if (!strcmp(args[0], "backlog")) { /* backlog */
4929 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004930 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004931
4932 if (*(args[1]) == 0) {
4933 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004936 }
4937 curproxy->backlog = atol(args[1]);
4938 }
Willy Tarreau86034312006-12-29 00:10:33 +01004939 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004940 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004941 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004942
Willy Tarreau86034312006-12-29 00:10:33 +01004943 if (*(args[1]) == 0) {
4944 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004945 err_code |= ERR_ALERT | ERR_FATAL;
4946 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004947 }
4948 curproxy->fullconn = atol(args[1]);
4949 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004950 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4951 if (*(args[1]) == 0) {
4952 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004953 err_code |= ERR_ALERT | ERR_FATAL;
4954 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004956 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4957 if (err) {
4958 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4959 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004960 err_code |= ERR_ALERT | ERR_FATAL;
4961 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004962 }
4963 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004964 }
4965 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004966 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004967 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004968 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004969
Willy Tarreaubaaee002006-06-26 02:48:02 +02004970 if (curproxy == &defproxy) {
4971 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004972 err_code |= ERR_ALERT | ERR_FATAL;
4973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004974 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004975 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004976 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004977
Willy Tarreau902636f2013-03-10 19:44:48 +01004978 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004979 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004980 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004981 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004982 goto out;
4983 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004984
4985 proto = protocol_by_family(sk->ss_family);
4986 if (!proto || !proto->connect) {
4987 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4988 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004989 err_code |= ERR_ALERT | ERR_FATAL;
4990 goto out;
4991 }
4992
4993 if (port1 != port2) {
4994 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4995 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004996 err_code |= ERR_ALERT | ERR_FATAL;
4997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004998 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004999
5000 if (!port1) {
5001 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5002 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005003 err_code |= ERR_ALERT | ERR_FATAL;
5004 goto out;
5005 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005006
Willy Tarreaud5191e72010-02-09 20:50:45 +01005007 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005008 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005009 }
5010 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005011 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005012 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005013
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005014 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5015 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005016 err_code |= ERR_ALERT | ERR_FATAL;
5017 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005019 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005020 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005021 /**
5022 * The syntax for hash-type config element is
5023 * hash-type {map-based|consistent} [[<algo>] avalanche]
5024 *
5025 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5026 */
5027 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005028
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005029 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5030 err_code |= ERR_WARN;
5031
5032 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005033 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5034 }
5035 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005036 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5037 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005038 else if (strcmp(args[1], "avalanche") == 0) {
5039 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]);
5040 err_code |= ERR_ALERT | ERR_FATAL;
5041 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005042 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005043 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005044 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005045 err_code |= ERR_ALERT | ERR_FATAL;
5046 goto out;
5047 }
Bhaskar98634f02013-10-29 23:30:51 -04005048
5049 /* set the hash function to use */
5050 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005051 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005052 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005053
5054 /* if consistent with no argument, then avalanche modifier is also applied */
5055 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5056 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005057 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005058 /* set the hash function */
5059 if (!strcmp(args[2], "sdbm")) {
5060 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5061 }
5062 else if (!strcmp(args[2], "djb2")) {
5063 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005064 }
5065 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005066 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005067 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005068 else if (!strcmp(args[2], "crc32")) {
5069 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5070 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005071 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005072 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 -05005073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
5075 }
5076
5077 /* set the hash modifier */
5078 if (!strcmp(args[3], "avalanche")) {
5079 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5080 }
5081 else if (*args[3]) {
5082 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5083 err_code |= ERR_ALERT | ERR_FATAL;
5084 goto out;
5085 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005086 }
William Lallemanda73203e2012-03-12 12:48:57 +01005087 }
William Lallemanda73203e2012-03-12 12:48:57 +01005088 else if (strcmp(args[0], "unique-id-format") == 0) {
5089 if (!*(args[1])) {
5090 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
William Lallemand3203ff42012-11-11 17:30:56 +01005094 if (*(args[2])) {
5095 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5096 err_code |= ERR_ALERT | ERR_FATAL;
5097 goto out;
5098 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005099 free(curproxy->conf.uniqueid_format_string);
5100 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005101
Willy Tarreau62a61232013-04-12 18:13:46 +02005102 free(curproxy->conf.uif_file);
5103 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5104 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005105 }
William Lallemanda73203e2012-03-12 12:48:57 +01005106
5107 else if (strcmp(args[0], "unique-id-header") == 0) {
5108 if (!*(args[1])) {
5109 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5110 err_code |= ERR_ALERT | ERR_FATAL;
5111 goto out;
5112 }
5113 free(curproxy->header_unique_id);
5114 curproxy->header_unique_id = strdup(args[1]);
5115 }
5116
William Lallemand723b73a2012-02-08 16:37:49 +01005117 else if (strcmp(args[0], "log-format") == 0) {
5118 if (!*(args[1])) {
5119 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5120 err_code |= ERR_ALERT | ERR_FATAL;
5121 goto out;
5122 }
William Lallemand3203ff42012-11-11 17:30:56 +01005123 if (*(args[2])) {
5124 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5125 err_code |= ERR_ALERT | ERR_FATAL;
5126 goto out;
5127 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005128
Willy Tarreau62a61232013-04-12 18:13:46 +02005129 if (curproxy->conf.logformat_string != default_http_log_format &&
5130 curproxy->conf.logformat_string != default_tcp_log_format &&
5131 curproxy->conf.logformat_string != clf_http_log_format)
5132 free(curproxy->conf.logformat_string);
5133 curproxy->conf.logformat_string = strdup(args[1]);
5134
5135 free(curproxy->conf.lfs_file);
5136 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5137 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005138
5139 /* get a chance to improve log-format error reporting by
5140 * reporting the correct line-number when possible.
5141 */
5142 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5143 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5144 file, linenum, curproxy->id);
5145 err_code |= ERR_WARN;
5146 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005147 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005148 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5149 if (*(args[1]) == 0) {
5150 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5151 err_code |= ERR_ALERT | ERR_FATAL;
5152 goto out;
5153 }
5154 free(curproxy->log_tag);
5155 curproxy->log_tag = strdup(args[1]);
5156 }
William Lallemand0f99e342011-10-12 17:50:54 +02005157 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5158 /* delete previous herited or defined syslog servers */
5159 struct logsrv *back;
5160
5161 if (*(args[1]) != 0) {
5162 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5163 err_code |= ERR_ALERT | ERR_FATAL;
5164 goto out;
5165 }
5166
William Lallemand723b73a2012-02-08 16:37:49 +01005167 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5168 LIST_DEL(&tmplogsrv->list);
5169 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005170 }
5171 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005172 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005173 struct logsrv *logsrv;
5174
Willy Tarreaubaaee002006-06-26 02:48:02 +02005175 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005176 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005177 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005178 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005179 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005180 LIST_INIT(&node->list);
5181 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5182 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005183 }
5184 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005185 struct sockaddr_storage *sk;
5186 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005187 int arg = 0;
5188 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005189
5190 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005191
Willy Tarreau18324f52014-06-27 18:10:07 +02005192 /* just after the address, a length may be specified */
5193 if (strcmp(args[arg+2], "len") == 0) {
5194 len = atoi(args[arg+3]);
5195 if (len < 80 || len > 65535) {
5196 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5197 file, linenum, args[arg+3]);
5198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
5200 }
5201 logsrv->maxlen = len;
5202
5203 /* skip these two args */
5204 arg += 2;
5205 }
5206 else
5207 logsrv->maxlen = MAX_SYSLOG_LEN;
5208
5209 if (logsrv->maxlen > global.max_syslog_len) {
5210 global.max_syslog_len = logsrv->maxlen;
5211 logline = realloc(logline, global.max_syslog_len + 1);
5212 }
5213
5214 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005215 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005216 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005217 err_code |= ERR_ALERT | ERR_FATAL;
5218 goto out;
5219
Willy Tarreaubaaee002006-06-26 02:48:02 +02005220 }
5221
William Lallemand0f99e342011-10-12 17:50:54 +02005222 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005223 if (*(args[arg+3])) {
5224 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005225 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005226 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005227 err_code |= ERR_ALERT | ERR_FATAL;
5228 goto out;
5229
Willy Tarreaubaaee002006-06-26 02:48:02 +02005230 }
5231 }
5232
William Lallemand0f99e342011-10-12 17:50:54 +02005233 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005234 if (*(args[arg+4])) {
5235 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005236 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005237 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005238 err_code |= ERR_ALERT | ERR_FATAL;
5239 goto out;
5240
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005241 }
5242 }
5243
Willy Tarreau902636f2013-03-10 19:44:48 +01005244 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005245 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005246 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005247 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005248 goto out;
5249 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005250
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005251 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005252
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005253 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005254 if (port1 != port2) {
5255 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5256 file, linenum, args[0], args[1]);
5257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
5259 }
5260
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005261 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005262 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005263 }
William Lallemand0f99e342011-10-12 17:50:54 +02005264
5265 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005266 }
5267 else {
5268 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5269 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005270 err_code |= ERR_ALERT | ERR_FATAL;
5271 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005272 }
5273 }
5274 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005275 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005276 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005277 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005278 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005279
Willy Tarreau977b8e42006-12-29 14:19:17 +01005280 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005281 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005282
Willy Tarreaubaaee002006-06-26 02:48:02 +02005283 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005284 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5285 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005286 err_code |= ERR_ALERT | ERR_FATAL;
5287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005288 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005289
5290 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005291 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5292 free(curproxy->conn_src.iface_name);
5293 curproxy->conn_src.iface_name = NULL;
5294 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005295
Willy Tarreau902636f2013-03-10 19:44:48 +01005296 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005297 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005298 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005299 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005300 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005301 goto out;
5302 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005303
5304 proto = protocol_by_family(sk->ss_family);
5305 if (!proto || !proto->connect) {
5306 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005307 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005308 err_code |= ERR_ALERT | ERR_FATAL;
5309 goto out;
5310 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005311
5312 if (port1 != port2) {
5313 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5314 file, linenum, args[0], args[1]);
5315 err_code |= ERR_ALERT | ERR_FATAL;
5316 goto out;
5317 }
5318
Willy Tarreauef9a3602012-12-08 22:29:20 +01005319 curproxy->conn_src.source_addr = *sk;
5320 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005321
5322 cur_arg = 2;
5323 while (*(args[cur_arg])) {
5324 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005325#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5326#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005327 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005328 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5329 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005330 err_code |= ERR_ALERT | ERR_FATAL;
5331 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005332 }
5333#endif
5334 if (!*args[cur_arg + 1]) {
5335 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5336 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005337 err_code |= ERR_ALERT | ERR_FATAL;
5338 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005339 }
5340
5341 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005342 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5343 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005344 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005345 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5346 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005347 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5348 char *name, *end;
5349
5350 name = args[cur_arg+1] + 7;
5351 while (isspace(*name))
5352 name++;
5353
5354 end = name;
5355 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5356 end++;
5357
Willy Tarreauef9a3602012-12-08 22:29:20 +01005358 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5359 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5360 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5361 curproxy->conn_src.bind_hdr_len = end - name;
5362 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5363 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5364 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005365
5366 /* now look for an occurrence number */
5367 while (isspace(*end))
5368 end++;
5369 if (*end == ',') {
5370 end++;
5371 name = end;
5372 if (*end == '-')
5373 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005374 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005375 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005376 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005377 }
5378
Willy Tarreauef9a3602012-12-08 22:29:20 +01005379 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005380 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5381 " occurrences values smaller than %d.\n",
5382 file, linenum, MAX_HDR_HISTORY);
5383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
5385 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005386 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005387 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005388
Willy Tarreau902636f2013-03-10 19:44:48 +01005389 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005390 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005391 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005392 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005393 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005394 goto out;
5395 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005396
5397 proto = protocol_by_family(sk->ss_family);
5398 if (!proto || !proto->connect) {
5399 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5400 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005401 err_code |= ERR_ALERT | ERR_FATAL;
5402 goto out;
5403 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005404
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005405 if (port1 != port2) {
5406 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5407 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005408 err_code |= ERR_ALERT | ERR_FATAL;
5409 goto out;
5410 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005411 curproxy->conn_src.tproxy_addr = *sk;
5412 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005413 }
5414 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005415#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005416 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005417#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005418#else /* no TPROXY support */
5419 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005420 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005423#endif
5424 cur_arg += 2;
5425 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005426 }
5427
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005428 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5429#ifdef SO_BINDTODEVICE
5430 if (!*args[cur_arg + 1]) {
5431 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5432 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005435 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005436 free(curproxy->conn_src.iface_name);
5437 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5438 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005439 global.last_checks |= LSTCHK_NETADM;
5440#else
5441 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5442 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005445#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005446 cur_arg += 2;
5447 continue;
5448 }
5449 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005450 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005453 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005454 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005455 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5456 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5457 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005460 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005461 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005462 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005463 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5464 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005465 err_code |= ERR_ALERT | ERR_FATAL;
5466 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005468
5469 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005470 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005471 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005472 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005474 }
5475 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005476 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005477 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005478 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005479 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005481 }
5482 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005483 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005484 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005485 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005486 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005487 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005488 }
5489 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005490 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005491 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005492 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005493 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005494 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005495 }
5496 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005497 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005498 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005499 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005500 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005501 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005502 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005503 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005504 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005505 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005506 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005507 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005508 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005509 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005510 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005511 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005512 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005513 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005514 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005515 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005516
5517 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5518 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 +01005519 }
5520 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005521 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005522 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005523 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005524 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005525 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005526
5527 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5528 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 +01005529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005530 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005531 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005532 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5533 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005534 err_code |= ERR_ALERT | ERR_FATAL;
5535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005536 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005537
5538 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005539 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005540 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005541 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 }
5544 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005545 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005546 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005547 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005548 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005550 }
5551 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005552 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005553 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005554 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005555 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 }
5558 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005559 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005560 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005561 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005562 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005564 }
5565 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005566 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005567 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005568 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005569 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005570 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005571 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005572 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005573 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005574 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005575 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005576 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005577 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005579 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005580 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005581
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582 if (curproxy == &defproxy) {
5583 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005584 err_code |= ERR_ALERT | ERR_FATAL;
5585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005586 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005587 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005588 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590 if (*(args[1]) == 0) {
5591 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005595
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005596 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005597 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5598 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5599 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005600 err_code |= ERR_ALERT | ERR_FATAL;
5601 goto out;
5602 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005603 err_code |= warnif_cond_conflicts(cond,
5604 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5605 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005606 }
5607 else if (*args[2]) {
5608 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5609 file, linenum, args[0], args[2]);
5610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
5612 }
5613
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005614 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005615 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005616 wl->s = strdup(args[1]);
5617 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005618 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005619 }
5620 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005621 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005622 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5623 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005624 err_code |= ERR_ALERT | ERR_FATAL;
5625 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005626 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005627
Willy Tarreauade5ec42010-01-28 19:33:49 +01005628 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005629 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005630 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005631 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 }
5634 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005635 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005636 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005637 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005638 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005640 }
5641 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005642 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005643 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005644 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005645 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005647 }
5648 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005649 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005650 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005652 err_code |= ERR_ALERT | ERR_FATAL;
5653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005654 }
5655
Willy Tarreauade5ec42010-01-28 19:33:49 +01005656 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005657 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005658 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005659 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005661 }
5662 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005663 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005664 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005665 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005666 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005668 }
5669 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005670 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005671 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005672 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005673 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005674 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675 }
5676 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005677 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005678
Willy Tarreaubaaee002006-06-26 02:48:02 +02005679 if (curproxy == &defproxy) {
5680 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005681 err_code |= ERR_ALERT | ERR_FATAL;
5682 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005683 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005684 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005685 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005686
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 if (*(args[1]) == 0) {
5688 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
5692
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005693 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005694 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5695 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5696 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005697 err_code |= ERR_ALERT | ERR_FATAL;
5698 goto out;
5699 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005700 err_code |= warnif_cond_conflicts(cond,
5701 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5702 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005703 }
5704 else if (*args[2]) {
5705 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5706 file, linenum, args[0], args[2]);
5707 err_code |= ERR_ALERT | ERR_FATAL;
5708 goto out;
5709 }
5710
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005711 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005712 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005713 wl->s = strdup(args[1]);
5714 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005715 }
5716 else if (!strcmp(args[0], "errorloc") ||
5717 !strcmp(args[0], "errorloc302") ||
5718 !strcmp(args[0], "errorloc303")) { /* error location */
5719 int errnum, errlen;
5720 char *err;
5721
Willy Tarreau977b8e42006-12-29 14:19:17 +01005722 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005723 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005724
Willy Tarreaubaaee002006-06-26 02:48:02 +02005725 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005726 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005729 }
5730
5731 errnum = atol(args[1]);
5732 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005733 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5734 err = malloc(errlen);
5735 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005736 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005737 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5738 err = malloc(errlen);
5739 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740 }
5741
Willy Tarreau0f772532006-12-23 20:51:41 +01005742 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5743 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005744 chunk_destroy(&curproxy->errmsg[rc]);
5745 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005746 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005749
5750 if (rc >= HTTP_ERR_SIZE) {
5751 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5752 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005753 free(err);
5754 }
5755 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005756 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5757 int errnum, errlen, fd;
5758 char *err;
5759 struct stat stat;
5760
5761 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005762 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005763
5764 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005765 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005766 err_code |= ERR_ALERT | ERR_FATAL;
5767 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005768 }
5769
5770 fd = open(args[2], O_RDONLY);
5771 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5772 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5773 file, linenum, args[2], args[1]);
5774 if (fd >= 0)
5775 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005778 }
5779
Willy Tarreau27a674e2009-08-17 07:23:33 +02005780 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005781 errlen = stat.st_size;
5782 } else {
5783 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005784 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005785 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005786 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005787 }
5788
5789 err = malloc(errlen); /* malloc() must succeed during parsing */
5790 errnum = read(fd, err, errlen);
5791 if (errnum != errlen) {
5792 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5793 file, linenum, args[2], args[1]);
5794 close(fd);
5795 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_ALERT | ERR_FATAL;
5797 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005798 }
5799 close(fd);
5800
5801 errnum = atol(args[1]);
5802 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5803 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005804 chunk_destroy(&curproxy->errmsg[rc]);
5805 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005806 break;
5807 }
5808 }
5809
5810 if (rc >= HTTP_ERR_SIZE) {
5811 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5812 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005813 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005814 free(err);
5815 }
5816 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005817 else if (!strcmp(args[0], "compression")) {
5818 struct comp *comp;
5819 if (curproxy->comp == NULL) {
5820 comp = calloc(1, sizeof(struct comp));
5821 curproxy->comp = comp;
5822 } else {
5823 comp = curproxy->comp;
5824 }
5825
5826 if (!strcmp(args[1], "algo")) {
5827 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005828 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005829
William Lallemand82fe75c2012-10-23 10:25:10 +02005830 cur_arg = 2;
5831 if (!*args[cur_arg]) {
5832 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5833 file, linenum, args[0]);
5834 err_code |= ERR_ALERT | ERR_FATAL;
5835 goto out;
5836 }
5837 while (*(args[cur_arg])) {
5838 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5839 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5840 file, linenum, args[0], args[cur_arg]);
5841 err_code |= ERR_ALERT | ERR_FATAL;
5842 goto out;
5843 }
William Lallemand552df672012-11-07 13:21:47 +01005844 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5845 curproxy->comp->algos->end(&ctx);
5846 } else {
5847 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5848 file, linenum, args[0], args[cur_arg]);
5849 err_code |= ERR_ALERT | ERR_FATAL;
5850 goto out;
5851 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005852 cur_arg ++;
5853 continue;
5854 }
5855 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005856 else if (!strcmp(args[1], "offload")) {
5857 comp->offload = 1;
5858 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005859 else if (!strcmp(args[1], "type")) {
5860 int cur_arg;
5861 cur_arg = 2;
5862 if (!*args[cur_arg]) {
5863 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5864 file, linenum, args[0]);
5865 err_code |= ERR_ALERT | ERR_FATAL;
5866 goto out;
5867 }
5868 while (*(args[cur_arg])) {
5869 comp_append_type(comp, args[cur_arg]);
5870 cur_arg ++;
5871 continue;
5872 }
5873 }
5874 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005875 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005876 file, linenum, args[0]);
5877 err_code |= ERR_ALERT | ERR_FATAL;
5878 goto out;
5879 }
5880 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005881 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005882 struct cfg_kw_list *kwl;
5883 int index;
5884
5885 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5886 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5887 if (kwl->kw[index].section != CFG_LISTEN)
5888 continue;
5889 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5890 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005891 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005892 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005893 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005894 err_code |= ERR_ALERT | ERR_FATAL;
5895 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005896 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005897 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005898 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005899 err_code |= ERR_WARN;
5900 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005901 }
Willy Tarreau93893792009-07-23 13:19:11 +02005902 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005903 }
5904 }
5905 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005906
Willy Tarreau6daf3432008-01-22 16:44:08 +01005907 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005908 err_code |= ERR_ALERT | ERR_FATAL;
5909 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 }
Willy Tarreau93893792009-07-23 13:19:11 +02005911 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005912 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005913 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914}
5915
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005916int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005917cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5918{
5919#ifdef CONFIG_HAP_NS
5920 const char *err;
5921 const char *item = args[0];
5922
5923 if (!strcmp(item, "namespace_list")) {
5924 return 0;
5925 }
5926 else if (!strcmp(item, "namespace")) {
5927 size_t idx = 1;
5928 const char *current;
5929 while (*(current = args[idx++])) {
5930 err = invalid_char(current);
5931 if (err) {
5932 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5933 file, linenum, *err, item, current);
5934 return ERR_ALERT | ERR_FATAL;
5935 }
5936
5937 if (netns_store_lookup(current, strlen(current))) {
5938 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5939 file, linenum, current);
5940 return ERR_ALERT | ERR_FATAL;
5941 }
5942 if (!netns_store_insert(current)) {
5943 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5944 file, linenum, current);
5945 return ERR_ALERT | ERR_FATAL;
5946 }
5947 }
5948 }
5949
5950 return 0;
5951#else
5952 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5953 file, linenum);
5954 return ERR_ALERT | ERR_FATAL;
5955#endif
5956}
5957
5958int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005959cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5960{
5961
5962 int err_code = 0;
5963 const char *err;
5964
5965 if (!strcmp(args[0], "userlist")) { /* new userlist */
5966 struct userlist *newul;
5967
5968 if (!*args[1]) {
5969 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5970 file, linenum, args[0]);
5971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
5973 }
5974
5975 err = invalid_char(args[1]);
5976 if (err) {
5977 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5978 file, linenum, *err, args[0], args[1]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
5982
5983 for (newul = userlist; newul; newul = newul->next)
5984 if (!strcmp(newul->name, args[1])) {
5985 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5986 file, linenum, args[1]);
5987 err_code |= ERR_WARN;
5988 goto out;
5989 }
5990
5991 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5992 if (!newul) {
5993 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5994 err_code |= ERR_ALERT | ERR_ABORT;
5995 goto out;
5996 }
5997
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005998 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01005999 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006000 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6001 err_code |= ERR_ALERT | ERR_ABORT;
6002 goto out;
6003 }
6004
6005 newul->next = userlist;
6006 userlist = newul;
6007
6008 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006009 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006010 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006011 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006012
6013 if (!*args[1]) {
6014 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6015 file, linenum, args[0]);
6016 err_code |= ERR_ALERT | ERR_FATAL;
6017 goto out;
6018 }
6019
6020 err = invalid_char(args[1]);
6021 if (err) {
6022 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6023 file, linenum, *err, args[0], args[1]);
6024 err_code |= ERR_ALERT | ERR_FATAL;
6025 goto out;
6026 }
6027
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006028 for (ag = userlist->groups; ag; ag = ag->next)
6029 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006030 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6031 file, linenum, args[1], userlist->name);
6032 err_code |= ERR_ALERT;
6033 goto out;
6034 }
6035
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006036 ag = calloc(1, sizeof(*ag));
6037 if (!ag) {
6038 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6039 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006040 goto out;
6041 }
6042
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006043 ag->name = strdup(args[1]);
6044 if (!ag) {
6045 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6046 err_code |= ERR_ALERT | ERR_ABORT;
6047 goto out;
6048 }
6049
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006050 cur_arg = 2;
6051
6052 while (*args[cur_arg]) {
6053 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006054 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006055 cur_arg += 2;
6056 continue;
6057 } else {
6058 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6059 file, linenum, args[0]);
6060 err_code |= ERR_ALERT | ERR_FATAL;
6061 goto out;
6062 }
6063 }
6064
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006065 ag->next = userlist->groups;
6066 userlist->groups = ag;
6067
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006068 } else if (!strcmp(args[0], "user")) { /* new user */
6069 struct auth_users *newuser;
6070 int cur_arg;
6071
6072 if (!*args[1]) {
6073 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6074 file, linenum, args[0]);
6075 err_code |= ERR_ALERT | ERR_FATAL;
6076 goto out;
6077 }
6078
6079 for (newuser = userlist->users; newuser; newuser = newuser->next)
6080 if (!strcmp(newuser->user, args[1])) {
6081 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6082 file, linenum, args[1], userlist->name);
6083 err_code |= ERR_ALERT;
6084 goto out;
6085 }
6086
6087 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6088 if (!newuser) {
6089 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6090 err_code |= ERR_ALERT | ERR_ABORT;
6091 goto out;
6092 }
6093
6094 newuser->user = strdup(args[1]);
6095
6096 newuser->next = userlist->users;
6097 userlist->users = newuser;
6098
6099 cur_arg = 2;
6100
6101 while (*args[cur_arg]) {
6102 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006103#ifdef CONFIG_HAP_CRYPT
6104 if (!crypt("", args[cur_arg + 1])) {
6105 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6106 file, linenum, newuser->user);
6107 err_code |= ERR_ALERT | ERR_FATAL;
6108 goto out;
6109 }
6110#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006111 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6112 file, linenum);
6113 err_code |= ERR_ALERT;
6114#endif
6115 newuser->pass = strdup(args[cur_arg + 1]);
6116 cur_arg += 2;
6117 continue;
6118 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6119 newuser->pass = strdup(args[cur_arg + 1]);
6120 newuser->flags |= AU_O_INSECURE;
6121 cur_arg += 2;
6122 continue;
6123 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006124 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006125 cur_arg += 2;
6126 continue;
6127 } else {
6128 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6129 file, linenum, args[0]);
6130 err_code |= ERR_ALERT | ERR_FATAL;
6131 goto out;
6132 }
6133 }
6134 } else {
6135 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6136 err_code |= ERR_ALERT | ERR_FATAL;
6137 }
6138
6139out:
6140 return err_code;
6141}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142
6143/*
6144 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006145 * Returns the error code, 0 if OK, or any combination of :
6146 * - ERR_ABORT: must abort ASAP
6147 * - ERR_FATAL: we can continue parsing but not start the service
6148 * - ERR_WARN: a warning has been emitted
6149 * - ERR_ALERT: an alert has been emitted
6150 * Only the two first ones can stop processing, the two others are just
6151 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006153int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006155 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 FILE *f;
6157 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006158 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006159 struct cfg_section *cs = NULL;
6160 struct cfg_section *ics;
6161
6162 /* Register internal sections */
6163 if (!cfg_register_section("listen", cfg_parse_listen) ||
6164 !cfg_register_section("frontend", cfg_parse_listen) ||
6165 !cfg_register_section("backend", cfg_parse_listen) ||
6166 !cfg_register_section("ruleset", cfg_parse_listen) ||
6167 !cfg_register_section("defaults", cfg_parse_listen) ||
6168 !cfg_register_section("global", cfg_parse_global) ||
6169 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006170 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006171 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006172 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006173 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006174
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175 if ((f=fopen(file,"r")) == NULL)
6176 return -1;
6177
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006178 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006179 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006180 char *end;
6181 char *args[MAX_LINE_ARGS + 1];
6182 char *line = thisline;
6183
Willy Tarreaubaaee002006-06-26 02:48:02 +02006184 linenum++;
6185
6186 end = line + strlen(line);
6187
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006188 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6189 /* Check if we reached the limit and the last char is not \n.
6190 * Watch out for the last line without the terminating '\n'!
6191 */
6192 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006193 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006194 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006195 }
6196
Willy Tarreaubaaee002006-06-26 02:48:02 +02006197 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006198 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 line++;
6200
6201 arg = 0;
6202 args[arg] = line;
6203
6204 while (*line && arg < MAX_LINE_ARGS) {
6205 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6206 * C equivalent value. Other combinations left unchanged (eg: \1).
6207 */
6208 if (*line == '\\') {
6209 int skip = 0;
6210 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6211 *line = line[1];
6212 skip = 1;
6213 }
6214 else if (line[1] == 'r') {
6215 *line = '\r';
6216 skip = 1;
6217 }
6218 else if (line[1] == 'n') {
6219 *line = '\n';
6220 skip = 1;
6221 }
6222 else if (line[1] == 't') {
6223 *line = '\t';
6224 skip = 1;
6225 }
6226 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006227 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006228 unsigned char hex1, hex2;
6229 hex1 = toupper(line[2]) - '0';
6230 hex2 = toupper(line[3]) - '0';
6231 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6232 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6233 *line = (hex1<<4) + hex2;
6234 skip = 3;
6235 }
6236 else {
6237 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006238 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006239 }
6240 }
6241 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006242 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006243 end -= skip;
6244 }
6245 line++;
6246 }
6247 else if (*line == '#' || *line == '\n' || *line == '\r') {
6248 /* end of string, end of loop */
6249 *line = 0;
6250 break;
6251 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006252 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006253 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006254 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006255 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006256 line++;
6257 args[++arg] = line;
6258 }
6259 else {
6260 line++;
6261 }
6262 }
6263
6264 /* empty line */
6265 if (!**args)
6266 continue;
6267
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006268 if (*line) {
6269 /* we had to stop due to too many args.
6270 * Let's terminate the string, print the offending part then cut the
6271 * last arg.
6272 */
6273 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6274 line++;
6275 *line = '\0';
6276
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006277 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006278 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 args[arg] = line;
6281 }
6282
Willy Tarreau540abe42007-05-02 20:50:16 +02006283 /* zero out remaining args and ensure that at least one entry
6284 * is zeroed out.
6285 */
6286 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006287 args[arg] = line;
6288 }
6289
Willy Tarreau3842f002009-06-14 11:39:52 +02006290 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006291 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006292 char *tmp;
6293
Willy Tarreau3842f002009-06-14 11:39:52 +02006294 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006295 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006296 for (arg=0; *args[arg+1]; arg++)
6297 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006298 *tmp = '\0'; // fix the next arg to \0
6299 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006300 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006301 else if (!strcmp(args[0], "default")) {
6302 kwm = KWM_DEF;
6303 for (arg=0; *args[arg+1]; arg++)
6304 args[arg] = args[arg+1]; // shift args after inversion
6305 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006306
William Lallemand0f99e342011-10-12 17:50:54 +02006307 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6308 strcmp(args[0], "log") != 0) {
6309 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006310 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006311 }
6312
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006313 /* detect section start */
6314 list_for_each_entry(ics, &sections, list) {
6315 if (strcmp(args[0], ics->section_name) == 0) {
6316 cursection = ics->section_name;
6317 cs = ics;
6318 break;
6319 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006320 }
6321
Willy Tarreaubaaee002006-06-26 02:48:02 +02006322 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006323 if (cs)
6324 err_code |= cs->section_parser(file, linenum, args, kwm);
6325 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006326 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006327 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006328 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006329
6330 if (err_code & ERR_ABORT)
6331 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006332 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006333 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006334 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006335 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006336}
6337
Willy Tarreau64ab6072014-09-16 12:17:36 +02006338/* This function propagates processes from frontend <from> to backend <to> so
6339 * that it is always guaranteed that a backend pointed to by a frontend is
6340 * bound to all of its processes. After that, if the target is a "listen"
6341 * instance, the function recursively descends the target's own targets along
6342 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6343 * checked first to ensure that <to> is already bound to all processes of
6344 * <from>, there is no risk of looping and we ensure to follow the shortest
6345 * path to the destination.
6346 *
6347 * It is possible to set <to> to NULL for the first call so that the function
6348 * takes care of visiting the initial frontend in <from>.
6349 *
6350 * It is important to note that the function relies on the fact that all names
6351 * have already been resolved.
6352 */
6353void propagate_processes(struct proxy *from, struct proxy *to)
6354{
6355 struct switching_rule *rule;
6356 struct hdr_exp *exp;
6357
6358 if (to) {
6359 /* check whether we need to go down */
6360 if (from->bind_proc &&
6361 (from->bind_proc & to->bind_proc) == from->bind_proc)
6362 return;
6363
6364 if (!from->bind_proc && !to->bind_proc)
6365 return;
6366
6367 to->bind_proc = from->bind_proc ?
6368 (to->bind_proc | from->bind_proc) : 0;
6369
6370 /* now propagate down */
6371 from = to;
6372 }
6373
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006374 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006375 return;
6376
Willy Tarreauf6b70012014-12-18 14:00:43 +01006377 if (from->state == PR_STSTOPPED)
6378 return;
6379
Willy Tarreau64ab6072014-09-16 12:17:36 +02006380 /* default_backend */
6381 if (from->defbe.be)
6382 propagate_processes(from, from->defbe.be);
6383
6384 /* use_backend */
6385 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006386 if (rule->dynamic)
6387 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006388 to = rule->be.backend;
6389 propagate_processes(from, to);
6390 }
6391
6392 /* reqsetbe */
6393 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6394 if (exp->action != ACT_SETBE)
6395 continue;
6396 to = (struct proxy *)exp->replace;
6397 propagate_processes(from, to);
6398 }
6399}
6400
Willy Tarreaubb925012009-07-23 13:36:36 +02006401/*
6402 * Returns the error code, 0 if OK, or any combination of :
6403 * - ERR_ABORT: must abort ASAP
6404 * - ERR_FATAL: we can continue parsing but not start the service
6405 * - ERR_WARN: a warning has been emitted
6406 * - ERR_ALERT: an alert has been emitted
6407 * Only the two first ones can stop processing, the two others are just
6408 * indicators.
6409 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006410int check_config_validity()
6411{
6412 int cfgerr = 0;
6413 struct proxy *curproxy = NULL;
6414 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006415 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006416 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006417 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006418
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006419 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 /*
6421 * Now, check for the integrity of all that we have collected.
6422 */
6423
6424 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006425 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426
Willy Tarreau193b8c62012-11-22 00:17:38 +01006427 if (!global.tune.max_http_hdr)
6428 global.tune.max_http_hdr = MAX_HTTP_HDR;
6429
6430 if (!global.tune.cookie_len)
6431 global.tune.cookie_len = CAPTURE_LEN;
6432
6433 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6434
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006435 /* Post initialisation of the users and groups lists. */
6436 err_code = userlist_postinit();
6437 if (err_code != ERR_NONE)
6438 goto out;
6439
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006440 /* first, we will invert the proxy list order */
6441 curproxy = NULL;
6442 while (proxy) {
6443 struct proxy *next;
6444
6445 next = proxy->next;
6446 proxy->next = curproxy;
6447 curproxy = proxy;
6448 if (!next)
6449 break;
6450 proxy = next;
6451 }
6452
Willy Tarreau419ead82014-09-16 13:41:21 +02006453 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006454 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006455 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006456 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006457 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006458 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006459 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006460 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006461
Willy Tarreau050536d2012-10-04 08:47:34 +02006462 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006463 /* proxy ID not set, use automatic numbering with first
6464 * spare entry starting with next_pxid.
6465 */
6466 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6467 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6468 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006469 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006470 next_pxid++;
6471
Willy Tarreau55ea7572007-06-17 19:56:27 +02006472
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006474 /* ensure we don't keep listeners uselessly bound */
6475 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006476 continue;
6477 }
6478
Willy Tarreau102df612014-05-07 23:56:38 +02006479 /* Check multi-process mode compatibility for the current proxy */
6480
6481 if (curproxy->bind_proc) {
6482 /* an explicit bind-process was specified, let's check how many
6483 * processes remain.
6484 */
6485 nbproc = popcount(curproxy->bind_proc);
6486
6487 curproxy->bind_proc &= nbits(global.nbproc);
6488 if (!curproxy->bind_proc && nbproc == 1) {
6489 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);
6490 curproxy->bind_proc = 1;
6491 }
6492 else if (!curproxy->bind_proc && nbproc > 1) {
6493 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);
6494 curproxy->bind_proc = 0;
6495 }
6496 }
6497
Willy Tarreau3d209582014-05-09 17:06:11 +02006498 /* check and reduce the bind-proc of each listener */
6499 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6500 unsigned long mask;
6501
6502 if (!bind_conf->bind_proc)
6503 continue;
6504
6505 mask = nbits(global.nbproc);
6506 if (curproxy->bind_proc)
6507 mask &= curproxy->bind_proc;
6508 /* mask cannot be null here thanks to the previous checks */
6509
6510 nbproc = popcount(bind_conf->bind_proc);
6511 bind_conf->bind_proc &= mask;
6512
6513 if (!bind_conf->bind_proc && nbproc == 1) {
6514 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",
6515 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6516 bind_conf->bind_proc = mask & ~(mask - 1);
6517 }
6518 else if (!bind_conf->bind_proc && nbproc > 1) {
6519 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",
6520 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6521 bind_conf->bind_proc = 0;
6522 }
6523 }
6524
Willy Tarreau102df612014-05-07 23:56:38 +02006525 if (global.nbproc > 1 && curproxy->table.peers.name) {
6526 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6527 curproxy->id);
6528 cfgerr++;
6529 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006530
Willy Tarreauff01a212009-03-15 13:46:16 +01006531 switch (curproxy->mode) {
6532 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006533 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006534 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006535 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6536 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006537 cfgerr++;
6538 }
6539
6540 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006541 Warning("config : servers will be ignored for %s '%s'.\n",
6542 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006543 break;
6544
6545 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006546 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006547 break;
6548
6549 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006550 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006551 break;
6552 }
6553
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006554 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006555 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006556 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006557 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6558 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006559 cfgerr++;
6560 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006561#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006562 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006563 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6564 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006565 cfgerr++;
6566 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006567#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006568 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006569 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6570 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006571 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006572 }
6573 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006574 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006575 /* If no LB algo is set in a backend, and we're not in
6576 * transparent mode, dispatch mode nor proxy mode, we
6577 * want to use balance roundrobin by default.
6578 */
6579 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6580 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006581 }
6582 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006583
Willy Tarreau1620ec32011-08-06 17:05:02 +02006584 if (curproxy->options & PR_O_DISPATCH)
6585 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6586 else if (curproxy->options & PR_O_HTTP_PROXY)
6587 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6588 else if (curproxy->options & PR_O_TRANSP)
6589 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006590
Willy Tarreau1620ec32011-08-06 17:05:02 +02006591 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6592 if (curproxy->options & PR_O_DISABLE404) {
6593 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6594 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6595 err_code |= ERR_WARN;
6596 curproxy->options &= ~PR_O_DISABLE404;
6597 }
6598 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6599 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6600 "send-state", proxy_type_str(curproxy), curproxy->id);
6601 err_code |= ERR_WARN;
6602 curproxy->options &= ~PR_O2_CHK_SNDST;
6603 }
Willy Tarreauef781042010-01-27 11:53:01 +01006604 }
6605
Simon Horman98637e52014-06-20 12:30:16 +09006606 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6607 if (!global.external_check) {
6608 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6609 curproxy->id, "option external-check");
6610 cfgerr++;
6611 }
6612 if (!curproxy->check_command) {
6613 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6614 curproxy->id, "option external-check");
6615 cfgerr++;
6616 }
6617 }
6618
Simon Horman64e34162015-02-06 11:11:57 +09006619 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006620 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6621 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006622 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6623 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006624 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6625 "to be present).\n",
6626 proxy_type_str(curproxy), curproxy->id);
6627 err_code |= ERR_WARN;
6628 free_email_alert(curproxy);
6629 }
6630 if (!curproxy->email_alert.myhostname)
6631 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006632 }
6633
Simon Horman98637e52014-06-20 12:30:16 +09006634 if (curproxy->check_command) {
6635 int clear = 0;
6636 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6637 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6638 "external-check command", proxy_type_str(curproxy), curproxy->id);
6639 err_code |= ERR_WARN;
6640 clear = 1;
6641 }
6642 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6643 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6644 curproxy->id, "external-check command");
6645 cfgerr++;
6646 }
6647 if (clear) {
6648 free(curproxy->check_command);
6649 curproxy->check_command = NULL;
6650 }
6651 }
6652
6653 if (curproxy->check_path) {
6654 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6655 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6656 "external-check path", proxy_type_str(curproxy), curproxy->id);
6657 err_code |= ERR_WARN;
6658 free(curproxy->check_path);
6659 curproxy->check_path = NULL;
6660 }
6661 }
6662
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006663 /* if a default backend was specified, let's find it */
6664 if (curproxy->defbe.name) {
6665 struct proxy *target;
6666
Alex Williams96532db2009-11-01 21:27:13 -05006667 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006668 if (!target) {
6669 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6670 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006671 cfgerr++;
6672 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006673 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6674 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006675 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006676 } else {
6677 free(curproxy->defbe.name);
6678 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006679
6680 /* Emit a warning if this proxy also has some servers */
6681 if (curproxy->srv) {
6682 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6683 curproxy->id);
6684 err_code |= ERR_WARN;
6685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006686 }
6687 }
6688
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006689 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006690 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6691 /* map jump target for ACT_SETBE in req_rep chain */
6692 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006693 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006694 struct proxy *target;
6695
Willy Tarreaua496b602006-12-17 23:15:24 +01006696 if (exp->action != ACT_SETBE)
6697 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006698
Alex Williams96532db2009-11-01 21:27:13 -05006699 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006700 if (!target) {
6701 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6702 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006703 cfgerr++;
6704 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006705 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6706 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006707 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006708 } else {
6709 free((void *)exp->replace);
6710 exp->replace = (const char *)target;
6711 }
6712 }
6713 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006714
6715 /* find the target proxy for 'use_backend' rules */
6716 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006717 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006718 struct logformat_node *node;
6719 char *pxname;
6720
6721 /* Try to parse the string as a log format expression. If the result
6722 * of the parsing is only one entry containing a simple string, then
6723 * it's a standard string corresponding to a static rule, thus the
6724 * parsing is cancelled and be.name is restored to be resolved.
6725 */
6726 pxname = rule->be.name;
6727 LIST_INIT(&rule->be.expr);
6728 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6729 curproxy->conf.args.file, curproxy->conf.args.line);
6730 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6731
6732 if (!LIST_ISEMPTY(&rule->be.expr)) {
6733 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6734 rule->dynamic = 1;
6735 free(pxname);
6736 continue;
6737 }
6738 /* simple string: free the expression and fall back to static rule */
6739 free(node->arg);
6740 free(node);
6741 }
6742
6743 rule->dynamic = 0;
6744 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006745
Alex Williams96532db2009-11-01 21:27:13 -05006746 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006747
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006748 if (!target) {
6749 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6750 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006751 cfgerr++;
6752 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006753 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6754 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006755 cfgerr++;
6756 } else {
6757 free((void *)rule->be.name);
6758 rule->be.backend = target;
6759 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006760 }
6761
Willy Tarreau64ab6072014-09-16 12:17:36 +02006762 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006763 list_for_each_entry(srule, &curproxy->server_rules, list) {
6764 struct server *target = findserver(curproxy, srule->srv.name);
6765
6766 if (!target) {
6767 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6768 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6769 cfgerr++;
6770 continue;
6771 }
6772 free((void *)srule->srv.name);
6773 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006774 }
6775
Emeric Brunb982a3d2010-01-04 15:45:53 +01006776 /* find the target table for 'stick' rules */
6777 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6778 struct proxy *target;
6779
Emeric Brun1d33b292010-01-04 15:47:17 +01006780 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6781 if (mrule->flags & STK_IS_STORE)
6782 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6783
Emeric Brunb982a3d2010-01-04 15:45:53 +01006784 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006785 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006786 else
6787 target = curproxy;
6788
6789 if (!target) {
6790 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6791 curproxy->id, mrule->table.name);
6792 cfgerr++;
6793 }
6794 else if (target->table.size == 0) {
6795 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6796 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6797 cfgerr++;
6798 }
Willy Tarreau12785782012-04-27 21:37:17 +02006799 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6800 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006801 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6802 cfgerr++;
6803 }
6804 else {
6805 free((void *)mrule->table.name);
6806 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006807 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006808 }
6809 }
6810
6811 /* find the target table for 'store response' rules */
6812 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6813 struct proxy *target;
6814
Emeric Brun1d33b292010-01-04 15:47:17 +01006815 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6816
Emeric Brunb982a3d2010-01-04 15:45:53 +01006817 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006818 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006819 else
6820 target = curproxy;
6821
6822 if (!target) {
6823 Alert("Proxy '%s': unable to find store table '%s'.\n",
6824 curproxy->id, mrule->table.name);
6825 cfgerr++;
6826 }
6827 else if (target->table.size == 0) {
6828 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6829 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6830 cfgerr++;
6831 }
Willy Tarreau12785782012-04-27 21:37:17 +02006832 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6833 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006834 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6835 cfgerr++;
6836 }
6837 else {
6838 free((void *)mrule->table.name);
6839 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006840 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006841 }
6842 }
6843
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006844 /* find the target table for 'tcp-request' layer 4 rules */
6845 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6846 struct proxy *target;
6847
Willy Tarreaub4c84932013-07-23 19:15:30 +02006848 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006849 continue;
6850
6851 if (trule->act_prm.trk_ctr.table.n)
6852 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6853 else
6854 target = curproxy;
6855
6856 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006857 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6858 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006859 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006860 cfgerr++;
6861 }
6862 else if (target->table.size == 0) {
6863 Alert("Proxy '%s': table '%s' used but not configured.\n",
6864 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6865 cfgerr++;
6866 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006867 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6868 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6869 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 +01006870 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006871 cfgerr++;
6872 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006873 else {
6874 free(trule->act_prm.trk_ctr.table.n);
6875 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006876 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006877 * to pass a list of counters to track and allocate them right here using
6878 * stktable_alloc_data_type().
6879 */
6880 }
6881 }
6882
Willy Tarreaud1f96522010-08-03 19:34:32 +02006883 /* find the target table for 'tcp-request' layer 6 rules */
6884 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6885 struct proxy *target;
6886
Willy Tarreaub4c84932013-07-23 19:15:30 +02006887 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006888 continue;
6889
6890 if (trule->act_prm.trk_ctr.table.n)
6891 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6892 else
6893 target = curproxy;
6894
6895 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006896 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6897 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006898 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006899 cfgerr++;
6900 }
6901 else if (target->table.size == 0) {
6902 Alert("Proxy '%s': table '%s' used but not configured.\n",
6903 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6904 cfgerr++;
6905 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006906 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6907 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6908 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 +01006909 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006910 cfgerr++;
6911 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006912 else {
6913 free(trule->act_prm.trk_ctr.table.n);
6914 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006915 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006916 * to pass a list of counters to track and allocate them right here using
6917 * stktable_alloc_data_type().
6918 */
6919 }
6920 }
6921
Willy Tarreau09448f72014-06-25 18:12:15 +02006922 /* find the target table for 'http-request' layer 7 rules */
6923 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6924 struct proxy *target;
6925
6926 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6927 continue;
6928
6929 if (hrqrule->act_prm.trk_ctr.table.n)
6930 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6931 else
6932 target = curproxy;
6933
6934 if (!target) {
6935 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6936 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6937 http_req_trk_idx(hrqrule->action));
6938 cfgerr++;
6939 }
6940 else if (target->table.size == 0) {
6941 Alert("Proxy '%s': table '%s' used but not configured.\n",
6942 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6943 cfgerr++;
6944 }
6945 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6946 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6947 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6948 http_req_trk_idx(hrqrule->action));
6949 cfgerr++;
6950 }
6951 else {
6952 free(hrqrule->act_prm.trk_ctr.table.n);
6953 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6954 /* Note: if we decide to enhance the track-sc syntax, we may be able
6955 * to pass a list of counters to track and allocate them right here using
6956 * stktable_alloc_data_type().
6957 */
6958 }
6959 }
6960
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006961 /* move any "block" rules at the beginning of the http-request rules */
6962 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6963 /* insert block_rules into http_req_rules at the beginning */
6964 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6965 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6966 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6967 curproxy->http_req_rules.n = curproxy->block_rules.n;
6968 LIST_INIT(&curproxy->block_rules);
6969 }
6970
Emeric Brun32da3c42010-09-23 18:39:19 +02006971 if (curproxy->table.peers.name) {
6972 struct peers *curpeers = peers;
6973
6974 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6975 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6976 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006977 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006978 break;
6979 }
6980 }
6981
6982 if (!curpeers) {
6983 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6984 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006985 free((void *)curproxy->table.peers.name);
6986 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006987 cfgerr++;
6988 }
6989 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006990 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6991 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006992 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006993 cfgerr++;
6994 }
6995 }
6996
Simon Horman9dc49962015-01-30 11:22:59 +09006997
6998 if (curproxy->email_alert.mailers.name) {
6999 struct mailers *curmailers = mailers;
7000
7001 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7002 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7003 free(curproxy->email_alert.mailers.name);
7004 curproxy->email_alert.mailers.m = curmailers;
7005 curmailers->users++;
7006 break;
7007 }
7008 }
7009
7010 if (!curmailers) {
7011 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7012 curproxy->id, curproxy->email_alert.mailers.name);
7013 free_email_alert(curproxy);
7014 cfgerr++;
7015 }
7016 }
7017
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007018 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007019 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007020 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7021 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7022 "proxy", curproxy->id);
7023 cfgerr++;
7024 goto out_uri_auth_compat;
7025 }
7026
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007027 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007028 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007029 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007030 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007031
Willy Tarreau95fa4692010-02-01 13:05:50 +01007032 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7033 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007034
7035 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007036 uri_auth_compat_req[i++] = "realm";
7037 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7038 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007039
Willy Tarreau95fa4692010-02-01 13:05:50 +01007040 uri_auth_compat_req[i++] = "unless";
7041 uri_auth_compat_req[i++] = "{";
7042 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7043 uri_auth_compat_req[i++] = "}";
7044 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007045
Willy Tarreauff011f22011-01-06 17:51:27 +01007046 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7047 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007048 cfgerr++;
7049 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007050 }
7051
Willy Tarreauff011f22011-01-06 17:51:27 +01007052 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007053
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007054 if (curproxy->uri_auth->auth_realm) {
7055 free(curproxy->uri_auth->auth_realm);
7056 curproxy->uri_auth->auth_realm = NULL;
7057 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007058
7059 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007060 }
7061out_uri_auth_compat:
7062
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007063 /* compile the log format */
7064 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007065 if (curproxy->conf.logformat_string != default_http_log_format &&
7066 curproxy->conf.logformat_string != default_tcp_log_format &&
7067 curproxy->conf.logformat_string != clf_http_log_format)
7068 free(curproxy->conf.logformat_string);
7069 curproxy->conf.logformat_string = NULL;
7070 free(curproxy->conf.lfs_file);
7071 curproxy->conf.lfs_file = NULL;
7072 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007073 }
7074
Willy Tarreau62a61232013-04-12 18:13:46 +02007075 if (curproxy->conf.logformat_string) {
7076 curproxy->conf.args.ctx = ARGC_LOG;
7077 curproxy->conf.args.file = curproxy->conf.lfs_file;
7078 curproxy->conf.args.line = curproxy->conf.lfs_line;
7079 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007080 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007081 curproxy->conf.args.file = NULL;
7082 curproxy->conf.args.line = 0;
7083 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007084
Willy Tarreau62a61232013-04-12 18:13:46 +02007085 if (curproxy->conf.uniqueid_format_string) {
7086 curproxy->conf.args.ctx = ARGC_UIF;
7087 curproxy->conf.args.file = curproxy->conf.uif_file;
7088 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007089 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007090 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007091 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007092 curproxy->conf.args.file = NULL;
7093 curproxy->conf.args.line = 0;
7094 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007095
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007096 /* only now we can check if some args remain unresolved.
7097 * This must be done after the users and groups resolution.
7098 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007099 cfgerr += smp_resolve_args(curproxy);
7100 if (!cfgerr)
7101 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007102
Willy Tarreau2738a142006-07-08 17:28:09 +02007103 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007104 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007105 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007106 (!curproxy->timeout.connect ||
7107 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007108 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007109 " | While not properly invalid, you will certainly encounter various problems\n"
7110 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007111 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007112 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007113 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007114 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007115
Willy Tarreau1fa31262007-12-03 00:36:16 +01007116 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7117 * We must still support older configurations, so let's find out whether those
7118 * parameters have been set or must be copied from contimeouts.
7119 */
7120 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007121 if (!curproxy->timeout.tarpit ||
7122 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007123 /* tarpit timeout not set. We search in the following order:
7124 * default.tarpit, curr.connect, default.connect.
7125 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007126 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007127 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007128 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007129 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007130 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007131 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007132 }
7133 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007134 (!curproxy->timeout.queue ||
7135 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007136 /* queue timeout not set. We search in the following order:
7137 * default.queue, curr.connect, default.connect.
7138 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007139 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007140 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007141 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007142 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007143 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007144 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007145 }
7146 }
7147
Willy Tarreau1620ec32011-08-06 17:05:02 +02007148 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007149 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7150 curproxy->check_req = (char *)malloc(curproxy->check_len);
7151 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007152 }
7153
Willy Tarreau215663d2014-06-13 18:30:23 +02007154 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7155 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7156 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7157 proxy_type_str(curproxy), curproxy->id);
7158 err_code |= ERR_WARN;
7159 }
7160
Willy Tarreau193b8c62012-11-22 00:17:38 +01007161 /* ensure that cookie capture length is not too large */
7162 if (curproxy->capture_len >= global.tune.cookie_len) {
7163 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7164 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7165 err_code |= ERR_WARN;
7166 curproxy->capture_len = global.tune.cookie_len - 1;
7167 }
7168
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007169 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007170 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007171 curproxy->req_cap_pool = create_pool("ptrcap",
7172 curproxy->nb_req_cap * sizeof(char *),
7173 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007174 }
7175
7176 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007177 curproxy->rsp_cap_pool = create_pool("ptrcap",
7178 curproxy->nb_rsp_cap * sizeof(char *),
7179 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007180 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007181
Willy Tarreaubaaee002006-06-26 02:48:02 +02007182 /* first, we will invert the servers list order */
7183 newsrv = NULL;
7184 while (curproxy->srv) {
7185 struct server *next;
7186
7187 next = curproxy->srv->next;
7188 curproxy->srv->next = newsrv;
7189 newsrv = curproxy->srv;
7190 if (!next)
7191 break;
7192 curproxy->srv = next;
7193 }
7194
Willy Tarreau17edc812014-01-03 12:14:34 +01007195 /* Check that no server name conflicts. This causes trouble in the stats.
7196 * We only emit a warning for the first conflict affecting each server,
7197 * in order to avoid combinatory explosion if all servers have the same
7198 * name. We do that only for servers which do not have an explicit ID,
7199 * because these IDs were made also for distinguishing them and we don't
7200 * want to annoy people who correctly manage them.
7201 */
7202 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7203 struct server *other_srv;
7204
7205 if (newsrv->puid)
7206 continue;
7207
7208 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7209 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7210 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7211 newsrv->conf.file, newsrv->conf.line,
7212 proxy_type_str(curproxy), curproxy->id,
7213 newsrv->id, other_srv->conf.line);
7214 break;
7215 }
7216 }
7217 }
7218
Willy Tarreaudd701652010-05-25 23:03:02 +02007219 /* assign automatic UIDs to servers which don't have one yet */
7220 next_id = 1;
7221 newsrv = curproxy->srv;
7222 while (newsrv != NULL) {
7223 if (!newsrv->puid) {
7224 /* server ID not set, use automatic numbering with first
7225 * spare entry starting with next_svid.
7226 */
7227 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7228 newsrv->conf.id.key = newsrv->puid = next_id;
7229 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7230 }
7231 next_id++;
7232 newsrv = newsrv->next;
7233 }
7234
Willy Tarreau20697042007-11-15 23:26:18 +01007235 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007236 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007237
Willy Tarreau62c3be22012-01-20 13:12:32 +01007238 /*
7239 * If this server supports a maxconn parameter, it needs a dedicated
7240 * tasks to fill the emptied slots when a connection leaves.
7241 * Also, resolve deferred tracking dependency if needed.
7242 */
7243 newsrv = curproxy->srv;
7244 while (newsrv != NULL) {
7245 if (newsrv->minconn > newsrv->maxconn) {
7246 /* Only 'minconn' was specified, or it was higher than or equal
7247 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7248 * this will avoid further useless expensive computations.
7249 */
7250 newsrv->maxconn = newsrv->minconn;
7251 } else if (newsrv->maxconn && !newsrv->minconn) {
7252 /* minconn was not specified, so we set it to maxconn */
7253 newsrv->minconn = newsrv->maxconn;
7254 }
7255
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007256#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007257 if (newsrv->use_ssl || newsrv->check.use_ssl)
7258 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007259#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007260
Willy Tarreau2f075e92013-12-03 11:11:34 +01007261 /* set the check type on the server */
7262 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7263
Willy Tarreau62c3be22012-01-20 13:12:32 +01007264 if (newsrv->trackit) {
7265 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007266 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007267 char *pname, *sname;
7268
7269 pname = newsrv->trackit;
7270 sname = strrchr(pname, '/');
7271
7272 if (sname)
7273 *sname++ = '\0';
7274 else {
7275 sname = pname;
7276 pname = NULL;
7277 }
7278
7279 if (pname) {
7280 px = findproxy(pname, PR_CAP_BE);
7281 if (!px) {
7282 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7283 proxy_type_str(curproxy), curproxy->id,
7284 newsrv->id, pname);
7285 cfgerr++;
7286 goto next_srv;
7287 }
7288 } else
7289 px = curproxy;
7290
7291 srv = findserver(px, sname);
7292 if (!srv) {
7293 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7294 proxy_type_str(curproxy), curproxy->id,
7295 newsrv->id, sname);
7296 cfgerr++;
7297 goto next_srv;
7298 }
7299
Willy Tarreau32091232014-05-16 13:52:00 +02007300 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7301 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7302 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007303 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007304 "tracking as it does not have any check nor agent enabled.\n",
7305 proxy_type_str(curproxy), curproxy->id,
7306 newsrv->id, px->id, srv->id);
7307 cfgerr++;
7308 goto next_srv;
7309 }
7310
7311 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7312
7313 if (loop) {
7314 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7315 "belongs to a tracking chain looping back to %s/%s.\n",
7316 proxy_type_str(curproxy), curproxy->id,
7317 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007318 cfgerr++;
7319 goto next_srv;
7320 }
7321
7322 if (curproxy != px &&
7323 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7324 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7325 "tracking: disable-on-404 option inconsistency.\n",
7326 proxy_type_str(curproxy), curproxy->id,
7327 newsrv->id, px->id, srv->id);
7328 cfgerr++;
7329 goto next_srv;
7330 }
7331
7332 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007333 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007334 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007335 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007336 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007337 }
7338
7339 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007340 newsrv->tracknext = srv->trackers;
7341 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007342
7343 free(newsrv->trackit);
7344 newsrv->trackit = NULL;
7345 }
7346 next_srv:
7347 newsrv = newsrv->next;
7348 }
7349
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007350 /* We have to initialize the server lookup mechanism depending
7351 * on what LB algorithm was choosen.
7352 */
7353
7354 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7355 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7356 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007357 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7358 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7359 init_server_map(curproxy);
7360 } else {
7361 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7362 fwrr_init_server_groups(curproxy);
7363 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007364 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007365
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007366 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007367 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7368 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7369 fwlc_init_server_tree(curproxy);
7370 } else {
7371 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7372 fas_init_server_tree(curproxy);
7373 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007374 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007375
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007376 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007377 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7378 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7379 chash_init_server_tree(curproxy);
7380 } else {
7381 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7382 init_server_map(curproxy);
7383 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007384 break;
7385 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007386
7387 if (curproxy->options & PR_O_LOGASAP)
7388 curproxy->to_log &= ~LW_BYTES;
7389
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007390 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007391 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007392 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7393 proxy_type_str(curproxy), curproxy->id);
7394 err_code |= ERR_WARN;
7395 }
7396
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007397 if (curproxy->mode != PR_MODE_HTTP) {
7398 int optnum;
7399
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007400 if (curproxy->uri_auth) {
7401 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7402 proxy_type_str(curproxy), curproxy->id);
7403 err_code |= ERR_WARN;
7404 curproxy->uri_auth = NULL;
7405 }
7406
Willy Tarreau87cf5142011-08-19 22:57:24 +02007407 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007408 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7409 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7410 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007411 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007412 }
7413
7414 if (curproxy->options & PR_O_ORGTO) {
7415 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7416 "originalto", proxy_type_str(curproxy), curproxy->id);
7417 err_code |= ERR_WARN;
7418 curproxy->options &= ~PR_O_ORGTO;
7419 }
7420
7421 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7422 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7423 (curproxy->cap & cfg_opts[optnum].cap) &&
7424 (curproxy->options & cfg_opts[optnum].val)) {
7425 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7426 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7427 err_code |= ERR_WARN;
7428 curproxy->options &= ~cfg_opts[optnum].val;
7429 }
7430 }
7431
7432 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7433 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7434 (curproxy->cap & cfg_opts2[optnum].cap) &&
7435 (curproxy->options2 & cfg_opts2[optnum].val)) {
7436 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7437 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7438 err_code |= ERR_WARN;
7439 curproxy->options2 &= ~cfg_opts2[optnum].val;
7440 }
7441 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007442
Pieter Baauwd551fb52013-05-08 22:49:23 +02007443#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007444 if (curproxy->conn_src.bind_hdr_occ) {
7445 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007446 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007447 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007448 err_code |= ERR_WARN;
7449 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007450#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007451 }
7452
Willy Tarreaubaaee002006-06-26 02:48:02 +02007453 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007454 * ensure that we're not cross-dressing a TCP server into HTTP.
7455 */
7456 newsrv = curproxy->srv;
7457 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007458 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007459 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7460 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007461 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007462 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007463
Willy Tarreau0cec3312011-10-31 13:49:26 +01007464 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7465 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7466 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7467 err_code |= ERR_WARN;
7468 }
7469
Willy Tarreauc93cd162014-05-13 15:54:22 +02007470 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007471 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7472 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7473 err_code |= ERR_WARN;
7474 }
7475
Pieter Baauwd551fb52013-05-08 22:49:23 +02007476#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007477 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7478 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007479 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 +01007480 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007481 err_code |= ERR_WARN;
7482 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007483#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007484 newsrv = newsrv->next;
7485 }
7486
Willy Tarreaue42bd962014-09-16 16:21:19 +02007487 /* check if we have a frontend with "tcp-request content" looking at L7
7488 * with no inspect-delay
7489 */
7490 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7491 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7492 if (trule->action == TCP_ACT_CAPTURE &&
7493 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7494 break;
7495 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7496 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7497 break;
7498 }
7499
7500 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7501 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7502 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7503 " This means that these rules will randomly find their contents. This can be fixed by"
7504 " setting the tcp-request inspect-delay.\n",
7505 proxy_type_str(curproxy), curproxy->id);
7506 err_code |= ERR_WARN;
7507 }
7508 }
7509
Willy Tarreauc1a21672009-08-16 22:37:44 +02007510 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007511 if (!curproxy->accept)
7512 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007513
Willy Tarreauc1a21672009-08-16 22:37:44 +02007514 if (curproxy->tcp_req.inspect_delay ||
7515 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007516 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007517
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007518 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007519 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007520 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007521 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007522
7523 /* both TCP and HTTP must check switching rules */
7524 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7525 }
7526
7527 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007528 if (curproxy->tcp_req.inspect_delay ||
7529 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7530 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7531
Emeric Brun97679e72010-09-23 17:56:44 +02007532 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7533 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7534
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007535 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007536 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007537 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007538 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007539
7540 /* If the backend does requires RDP cookie persistence, we have to
7541 * enable the corresponding analyser.
7542 */
7543 if (curproxy->options2 & PR_O2_RDPC_PRST)
7544 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7545 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007546 }
7547
7548 /***********************************************************/
7549 /* At this point, target names have already been resolved. */
7550 /***********************************************************/
7551
7552 /* Check multi-process mode compatibility */
7553
7554 if (global.nbproc > 1 && global.stats_fe) {
7555 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7556 unsigned long mask;
7557
7558 mask = nbits(global.nbproc);
7559 if (global.stats_fe->bind_proc)
7560 mask &= global.stats_fe->bind_proc;
7561
7562 if (bind_conf->bind_proc)
7563 mask &= bind_conf->bind_proc;
7564
7565 /* stop here if more than one process is used */
7566 if (popcount(mask) > 1)
7567 break;
7568 }
7569 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7570 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");
7571 }
7572 }
7573
7574 /* Make each frontend inherit bind-process from its listeners when not specified. */
7575 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7576 if (curproxy->bind_proc)
7577 continue;
7578
7579 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7580 unsigned long mask;
7581
7582 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7583 curproxy->bind_proc |= mask;
7584 }
7585
7586 if (!curproxy->bind_proc)
7587 curproxy->bind_proc = ~0UL;
7588 }
7589
7590 if (global.stats_fe) {
7591 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7592 unsigned long mask;
7593
7594 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7595 global.stats_fe->bind_proc |= mask;
7596 }
7597 if (!global.stats_fe->bind_proc)
7598 global.stats_fe->bind_proc = ~0UL;
7599 }
7600
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007601 /* propagate bindings from frontends to backends. Don't do it if there
7602 * are any fatal errors as we must not call it with unresolved proxies.
7603 */
7604 if (!cfgerr) {
7605 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7606 if (curproxy->cap & PR_CAP_FE)
7607 propagate_processes(curproxy, NULL);
7608 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007609 }
7610
7611 /* Bind each unbound backend to all processes when not specified. */
7612 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7613 if (curproxy->bind_proc)
7614 continue;
7615 curproxy->bind_proc = ~0UL;
7616 }
7617
7618 /*******************************************************/
7619 /* At this step, all proxies have a non-null bind_proc */
7620 /*******************************************************/
7621
7622 /* perform the final checks before creating tasks */
7623
7624 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7625 struct listener *listener;
7626 unsigned int next_id;
7627 int nbproc;
7628
7629 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007630
Emeric Brunc52962f2012-11-15 18:28:02 +01007631#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007632 /* Configure SSL for each bind line.
7633 * Note: if configuration fails at some point, the ->ctx member
7634 * remains NULL so that listeners can later detach.
7635 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007636 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007637 int alloc_ctx;
7638
Emeric Brunc52962f2012-11-15 18:28:02 +01007639 if (!bind_conf->is_ssl) {
7640 if (bind_conf->default_ctx) {
7641 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7642 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7643 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007644 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007645 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007646 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007647 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007648 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007649 cfgerr++;
7650 continue;
7651 }
7652
Emeric Brun8dc60392014-05-09 13:52:00 +02007653 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007654 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007655 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7656 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");
7657 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007658 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007659 cfgerr++;
7660 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007661 }
7662
Emeric Brunfc0421f2012-09-07 17:30:07 +02007663 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007664 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007665 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007666#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007667
Willy Tarreaue6b98942007-10-29 01:09:36 +01007668 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007669 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007670 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007671 if (!listener->luid) {
7672 /* listener ID not set, use automatic numbering with first
7673 * spare entry starting with next_luid.
7674 */
7675 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7676 listener->conf.id.key = listener->luid = next_id;
7677 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007678 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007679 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007680
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007681 /* enable separate counters */
7682 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7683 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007684 if (!listener->name)
7685 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007686 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007687
Willy Tarreaue6b98942007-10-29 01:09:36 +01007688 if (curproxy->options & PR_O_TCP_NOLING)
7689 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007690 if (!listener->maxconn)
7691 listener->maxconn = curproxy->maxconn;
7692 if (!listener->backlog)
7693 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007694 if (!listener->maxaccept)
7695 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7696
7697 /* we want to have an optimal behaviour on single process mode to
7698 * maximize the work at once, but in multi-process we want to keep
7699 * some fairness between processes, so we target half of the max
7700 * number of events to be balanced over all the processes the proxy
7701 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7702 * used to disable the limit.
7703 */
7704 if (listener->maxaccept > 0) {
7705 if (nbproc > 1)
7706 listener->maxaccept = (listener->maxaccept + 1) / 2;
7707 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7708 }
7709
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007710 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007711 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007712 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007713
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007714 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7715 listener->options |= LI_O_TCP_RULES;
7716
Willy Tarreaude3041d2010-05-31 10:56:17 +02007717 if (curproxy->mon_mask.s_addr)
7718 listener->options |= LI_O_CHK_MONNET;
7719
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007720 /* smart accept mode is automatic in HTTP mode */
7721 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007722 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007723 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7724 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007725 }
7726
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007727 /* Release unused SSL configs */
7728 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7729 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007730 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007731#ifdef USE_OPENSSL
7732 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007733 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007734 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007735 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007736 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007737 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007738#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007739 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007740
Willy Tarreau102df612014-05-07 23:56:38 +02007741 if (nbproc > 1) {
7742 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007743 int count, maxproc = 0;
7744
7745 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7746 count = popcount(bind_conf->bind_proc);
7747 if (count > maxproc)
7748 maxproc = count;
7749 }
7750 /* backends have 0, frontends have 1 or more */
7751 if (maxproc != 1)
7752 Warning("Proxy '%s': in multi-process mode, stats will be"
7753 " limited to process assigned to the current request.\n",
7754 curproxy->id);
7755
Willy Tarreau102df612014-05-07 23:56:38 +02007756 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7757 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7758 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007759 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007760 }
Willy Tarreau102df612014-05-07 23:56:38 +02007761 if (curproxy->appsession_name) {
7762 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7763 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007764 }
Willy Tarreau102df612014-05-07 23:56:38 +02007765 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7766 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7767 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007768 }
7769 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007770
7771 /* create the task associated with the proxy */
7772 curproxy->task = task_new();
7773 if (curproxy->task) {
7774 curproxy->task->context = curproxy;
7775 curproxy->task->process = manage_proxy;
7776 /* no need to queue, it will be done automatically if some
7777 * listener gets limited.
7778 */
7779 curproxy->task->expire = TICK_ETERNITY;
7780 } else {
7781 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7782 curproxy->id);
7783 cfgerr++;
7784 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007785 }
7786
Willy Tarreaufbb78422011-06-05 15:38:35 +02007787 /* automatically compute fullconn if not set. We must not do it in the
7788 * loop above because cross-references are not yet fully resolved.
7789 */
7790 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7791 /* If <fullconn> is not set, let's set it to 10% of the sum of
7792 * the possible incoming frontend's maxconns.
7793 */
7794 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7795 struct proxy *fe;
7796 int total = 0;
7797
7798 /* sum up the number of maxconns of frontends which
7799 * reference this backend at least once or which are
7800 * the same one ('listen').
7801 */
7802 for (fe = proxy; fe; fe = fe->next) {
7803 struct switching_rule *rule;
7804 struct hdr_exp *exp;
7805 int found = 0;
7806
7807 if (!(fe->cap & PR_CAP_FE))
7808 continue;
7809
7810 if (fe == curproxy) /* we're on a "listen" instance */
7811 found = 1;
7812
7813 if (fe->defbe.be == curproxy) /* "default_backend" */
7814 found = 1;
7815
7816 /* check if a "use_backend" rule matches */
7817 if (!found) {
7818 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007819 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007820 found = 1;
7821 break;
7822 }
7823 }
7824 }
7825
7826 /* check if a "reqsetbe" rule matches */
7827 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7828 if (exp->action == ACT_SETBE &&
7829 (struct proxy *)exp->replace == curproxy) {
7830 found = 1;
7831 break;
7832 }
7833 }
7834
7835 /* now we've checked all possible ways to reference a backend
7836 * from a frontend.
7837 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007838 if (!found)
7839 continue;
7840 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007841 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007842 /* we have the sum of the maxconns in <total>. We only
7843 * keep 10% of that sum to set the default fullconn, with
7844 * a hard minimum of 1 (to avoid a divide by zero).
7845 */
7846 curproxy->fullconn = (total + 9) / 10;
7847 if (!curproxy->fullconn)
7848 curproxy->fullconn = 1;
7849 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007850 }
7851
Willy Tarreau056f5682010-06-06 15:51:11 +02007852 /* initialize stick-tables on backend capable proxies. This must not
7853 * be done earlier because the data size may be discovered while parsing
7854 * other proxies.
7855 */
Godbach9703e662013-12-11 21:11:41 +08007856 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007857 if (curproxy->state == PR_STSTOPPED)
7858 continue;
7859
Godbach9703e662013-12-11 21:11:41 +08007860 if (!stktable_init(&curproxy->table)) {
7861 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7862 cfgerr++;
7863 }
7864 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007865
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007866 /*
7867 * Recount currently required checks.
7868 */
7869
7870 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7871 int optnum;
7872
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007873 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7874 if (curproxy->options & cfg_opts[optnum].val)
7875 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007876
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007877 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7878 if (curproxy->options2 & cfg_opts2[optnum].val)
7879 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007880 }
7881
Willy Tarreau122541c2011-09-07 21:24:49 +02007882 if (peers) {
7883 struct peers *curpeers = peers, **last;
7884 struct peer *p, *pb;
7885
7886 /* Remove all peers sections which don't have a valid listener.
7887 * This can happen when a peers section is never referenced and
7888 * does not contain a local peer.
7889 */
7890 last = &peers;
7891 while (*last) {
7892 curpeers = *last;
7893 if (curpeers->peers_fe) {
7894 last = &curpeers->next;
7895 continue;
7896 }
7897
7898 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7899 curpeers->id, localpeer);
7900
7901 p = curpeers->remote;
7902 while (p) {
7903 pb = p->next;
7904 free(p->id);
7905 free(p);
7906 p = pb;
7907 }
7908
7909 /* Destroy and unlink this curpeers section.
7910 * Note: curpeers is backed up into *last.
7911 */
7912 free(curpeers->id);
7913 curpeers = curpeers->next;
7914 free(*last);
7915 *last = curpeers;
7916 }
7917 }
7918
Simon Horman0d16a402015-01-30 11:22:58 +09007919 if (mailers) {
7920 struct mailers *curmailers = mailers, **last;
7921 struct mailer *m, *mb;
7922
7923 /* Remove all mailers sections which don't have a valid listener.
7924 * This can happen when a mailers section is never referenced.
7925 */
7926 last = &mailers;
7927 while (*last) {
7928 curmailers = *last;
7929 if (curmailers->users) {
7930 last = &curmailers->next;
7931 continue;
7932 }
7933
7934 Warning("Removing incomplete section 'mailers %s'.\n",
7935 curmailers->id);
7936
7937 m = curmailers->mailer_list;
7938 while (m) {
7939 mb = m->next;
7940 free(m->id);
7941 free(m);
7942 m = mb;
7943 }
7944
7945 /* Destroy and unlink this curmailers section.
7946 * Note: curmailers is backed up into *last.
7947 */
7948 free(curmailers->id);
7949 curmailers = curmailers->next;
7950 free(*last);
7951 *last = curmailers;
7952 }
7953 }
7954
Willy Tarreau34eb6712011-10-24 18:15:04 +02007955 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007956 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007957 MEM_F_SHARED);
7958
Willy Tarreaubb925012009-07-23 13:36:36 +02007959 if (cfgerr > 0)
7960 err_code |= ERR_ALERT | ERR_FATAL;
7961 out:
7962 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007963}
7964
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007965/*
7966 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7967 * parsing sessions.
7968 */
7969void cfg_register_keywords(struct cfg_kw_list *kwl)
7970{
7971 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7972}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007973
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007974/*
7975 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7976 */
7977void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7978{
7979 LIST_DEL(&kwl->list);
7980 LIST_INIT(&kwl->list);
7981}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007982
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007983/* this function register new section in the haproxy configuration file.
7984 * <section_name> is the name of this new section and <section_parser>
7985 * is the called parser. If two section declaration have the same name,
7986 * only the first declared is used.
7987 */
7988int cfg_register_section(char *section_name,
7989 int (*section_parser)(const char *, int, char **, int))
7990{
7991 struct cfg_section *cs;
7992
7993 cs = calloc(1, sizeof(*cs));
7994 if (!cs) {
7995 Alert("register section '%s': out of memory.\n", section_name);
7996 return 0;
7997 }
7998
7999 cs->section_name = section_name;
8000 cs->section_parser = section_parser;
8001
8002 LIST_ADDQ(&sections, &cs->list);
8003
8004 return 1;
8005}
8006
Willy Tarreaubaaee002006-06-26 02:48:02 +02008007/*
8008 * Local variables:
8009 * c-indent-level: 8
8010 * c-basic-offset: 8
8011 * End:
8012 */