blob: cdb65035b9276224cd76df21b3b9ff5e92383285 [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;
1887 l->timeout = &((struct proxy *)curpeers->peers_fe)->timeout.client;
1888 l->accept = session_accept;
1889 l->handler = process_session;
1890 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
1891 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
1892 global.maxsock += l->maxconn;
1893 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001894 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01001895 else {
1896 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
1897 file, linenum, args[0], args[1],
1898 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
1899 err_code |= ERR_FATAL;
1900 goto out;
1901 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001902 }
1903 } /* neither "peer" nor "peers" */
1904 else if (*args[0] != 0) {
1905 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
1906 err_code |= ERR_ALERT | ERR_FATAL;
1907 goto out;
1908 }
1909
1910out:
Willy Tarreau902636f2013-03-10 19:44:48 +01001911 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02001912 return err_code;
1913}
1914
Simon Horman0d16a402015-01-30 11:22:58 +09001915
1916/*
1917 * Parse a line in a <listen>, <frontend>, <backend> or <ruleset> section.
1918 * Returns the error code, 0 if OK, or any combination of :
1919 * - ERR_ABORT: must abort ASAP
1920 * - ERR_FATAL: we can continue parsing but not start the service
1921 * - ERR_WARN: a warning has been emitted
1922 * - ERR_ALERT: an alert has been emitted
1923 * Only the two first ones can stop processing, the two others are just
1924 * indicators.
1925 */
1926int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
1927{
1928 static struct mailers *curmailers = NULL;
1929 struct mailer *newmailer = NULL;
1930 const char *err;
1931 int err_code = 0;
1932 char *errmsg = NULL;
1933
1934 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
1935 if (!*args[1]) {
1936 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
1937 err_code |= ERR_ALERT | ERR_ABORT;
1938 goto out;
1939 }
1940
1941 err = invalid_char(args[1]);
1942 if (err) {
1943 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1944 file, linenum, *err, args[0], args[1]);
1945 err_code |= ERR_ALERT | ERR_ABORT;
1946 goto out;
1947 }
1948
1949 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
1950 /*
1951 * If there are two proxies with the same name only following
1952 * combinations are allowed:
1953 */
1954 if (strcmp(curmailers->id, args[1]) == 0) {
1955 Warning("Parsing [%s:%d]: mailers '%s' has same name as another mailers (declared at %s:%d).\n",
1956 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
1957 err_code |= ERR_WARN;
1958 }
1959 }
1960
1961 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
1962 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1963 err_code |= ERR_ALERT | ERR_ABORT;
1964 goto out;
1965 }
1966
1967 curmailers->next = mailers;
1968 mailers = curmailers;
1969 curmailers->conf.file = strdup(file);
1970 curmailers->conf.line = linenum;
1971 curmailers->id = strdup(args[1]);
1972 }
1973 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
1974 struct sockaddr_storage *sk;
1975 int port1, port2;
1976 struct protocol *proto;
1977
1978 if (!*args[2]) {
1979 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
1980 file, linenum, args[0]);
1981 err_code |= ERR_ALERT | ERR_FATAL;
1982 goto out;
1983 }
1984
1985 err = invalid_char(args[1]);
1986 if (err) {
1987 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
1988 file, linenum, *err, args[1]);
1989 err_code |= ERR_ALERT | ERR_FATAL;
1990 goto out;
1991 }
1992
1993 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
1994 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1995 err_code |= ERR_ALERT | ERR_ABORT;
1996 goto out;
1997 }
1998
1999 /* the mailers are linked backwards first */
2000 curmailers->count++;
2001 newmailer->next = curmailers->mailer_list;
2002 curmailers->mailer_list = newmailer;
2003 newmailer->mailers = curmailers;
2004 newmailer->conf.file = strdup(file);
2005 newmailer->conf.line = linenum;
2006
2007 newmailer->id = strdup(args[1]);
2008
2009 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2010 if (!sk) {
2011 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2012 err_code |= ERR_ALERT | ERR_FATAL;
2013 goto out;
2014 }
2015
2016 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002017 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2018 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002019 file, linenum, args[0], args[1]);
2020 err_code |= ERR_ALERT | ERR_FATAL;
2021 goto out;
2022 }
2023
2024 if (port1 != port2) {
2025 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2026 file, linenum, args[0], args[1], args[2]);
2027 err_code |= ERR_ALERT | ERR_FATAL;
2028 goto out;
2029 }
2030
2031 if (!port1) {
2032 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2033 file, linenum, args[0], args[1], args[2]);
2034 err_code |= ERR_ALERT | ERR_FATAL;
2035 goto out;
2036 }
2037
2038 newmailer->addr = *sk;
2039 newmailer->proto = proto;
2040 newmailer->xprt = &raw_sock;
2041 newmailer->sock_init_arg = NULL;
2042 } /* neither "mailer" nor "mailers" */
2043 else if (*args[0] != 0) {
2044 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2045 err_code |= ERR_ALERT | ERR_FATAL;
2046 goto out;
2047 }
2048
2049out:
2050 free(errmsg);
2051 return err_code;
2052}
2053
Simon Horman9dc49962015-01-30 11:22:59 +09002054static void free_email_alert(struct proxy *p)
2055{
2056 free(p->email_alert.mailers.name);
2057 p->email_alert.mailers.name = NULL;
2058 free(p->email_alert.from);
2059 p->email_alert.from = NULL;
2060 free(p->email_alert.to);
2061 p->email_alert.to = NULL;
2062 free(p->email_alert.myhostname);
2063 p->email_alert.myhostname = NULL;
2064}
2065
Willy Tarreau3842f002009-06-14 11:39:52 +02002066int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002067{
2068 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002069 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002070 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002071 int rc;
2072 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002073 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002074 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002075 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002076 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002077 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002078
Willy Tarreau977b8e42006-12-29 14:19:17 +01002079 if (!strcmp(args[0], "listen"))
2080 rc = PR_CAP_LISTEN;
2081 else if (!strcmp(args[0], "frontend"))
2082 rc = PR_CAP_FE | PR_CAP_RS;
2083 else if (!strcmp(args[0], "backend"))
2084 rc = PR_CAP_BE | PR_CAP_RS;
2085 else if (!strcmp(args[0], "ruleset"))
2086 rc = PR_CAP_RS;
2087 else
2088 rc = PR_CAP_NONE;
2089
2090 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002091 struct ebpt_node *node;
2092
Willy Tarreaubaaee002006-06-26 02:48:02 +02002093 if (!*args[1]) {
2094 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2095 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2096 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002097 err_code |= ERR_ALERT | ERR_ABORT;
2098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002099 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002100
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002101 err = invalid_char(args[1]);
2102 if (err) {
2103 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2104 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002105 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002106 }
2107
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002108 for (node = ebis_lookup(&proxy_by_name, args[1]); node; node = ebpt_next(node)) {
2109 curproxy = container_of(node, struct proxy, conf.by_name);
2110
2111 if (strcmp(curproxy->id, args[1]) != 0)
2112 break;
2113
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002114 /*
2115 * If there are two proxies with the same name only following
2116 * combinations are allowed:
2117 *
2118 * listen backend frontend ruleset
2119 * listen - - - -
2120 * backend - - OK -
2121 * frontend - OK - -
2122 * ruleset - - - -
2123 */
2124
Willy Tarreau7cbc9152014-03-15 08:17:08 +01002125 if ((rc != (PR_CAP_FE|PR_CAP_RS) || curproxy->cap != (PR_CAP_BE|PR_CAP_RS)) &&
2126 (rc != (PR_CAP_BE|PR_CAP_RS) || curproxy->cap != (PR_CAP_FE|PR_CAP_RS))) {
Willy Tarreau092549f2009-10-04 21:11:42 +02002127 Warning("Parsing [%s:%d]: %s '%s' has same name as another %s (declared at %s:%d).\n",
2128 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2129 curproxy->conf.file, curproxy->conf.line);
Willy Tarreau93893792009-07-23 13:19:11 +02002130 err_code |= ERR_WARN;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002131 }
2132 }
2133
Willy Tarreaubaaee002006-06-26 02:48:02 +02002134 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2135 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002136 err_code |= ERR_ALERT | ERR_ABORT;
2137 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002138 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002139
Willy Tarreau97cb7802010-01-03 20:23:58 +01002140 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002141 curproxy->next = proxy;
2142 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002143 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2144 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002145 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002146 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002147 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002148 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002149
2150 /* parse the listener address if any */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002151 if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
Willy Tarreau4348fad2012-09-20 16:48:07 +02002152 struct listener *l;
Willy Tarreau81a81172012-09-18 20:52:35 +02002153
Willy Tarreau4348fad2012-09-20 16:48:07 +02002154 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[2]);
2155
Willy Tarreau902636f2013-03-10 19:44:48 +01002156 if (!str2listener(args[2], curproxy, bind_conf, file, linenum, &errmsg)) {
2157 if (errmsg && *errmsg) {
2158 indent_msg(&errmsg, 2);
2159 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002160 }
2161 else
2162 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address '%s'.\n",
2163 file, linenum, args[0], args[1], args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02002164 err_code |= ERR_FATAL;
2165 goto out;
2166 }
Willy Tarreau81a81172012-09-18 20:52:35 +02002167
Willy Tarreau4348fad2012-09-20 16:48:07 +02002168 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauc8b11092011-02-16 11:08:57 +01002169 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002170 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002171 }
2172
2173 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002174 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002175 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002176
Willy Tarreaubaaee002006-06-26 02:48:02 +02002177 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002178 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002179 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002180 curproxy->no_options = defproxy.no_options;
2181 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002182 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002183 curproxy->except_net = defproxy.except_net;
2184 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002185 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002186 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002187
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002188 if (defproxy.fwdfor_hdr_len) {
2189 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2190 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2191 }
2192
Willy Tarreaub86db342009-11-30 11:50:16 +01002193 if (defproxy.orgto_hdr_len) {
2194 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2195 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2196 }
2197
Mark Lamourinec2247f02012-01-04 13:02:01 -05002198 if (defproxy.server_id_hdr_len) {
2199 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2200 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2201 }
2202
Willy Tarreau977b8e42006-12-29 14:19:17 +01002203 if (curproxy->cap & PR_CAP_FE) {
2204 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002205 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002206 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002207
2208 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002209 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2210 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002211
2212 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2213 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002214
Willy Tarreau977b8e42006-12-29 14:19:17 +01002215 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002216 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002217 curproxy->fullconn = defproxy.fullconn;
2218 curproxy->conn_retries = defproxy.conn_retries;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002219 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002220
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002221 if (defproxy.check_req) {
2222 curproxy->check_req = calloc(1, defproxy.check_len);
2223 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2224 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002225 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002226
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002227 if (defproxy.expect_str) {
2228 curproxy->expect_str = strdup(defproxy.expect_str);
2229 if (defproxy.expect_regex) {
2230 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002231 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2232 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002233 }
2234 }
2235
Willy Tarreau67402132012-05-31 20:40:20 +02002236 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002237 if (defproxy.cookie_name)
2238 curproxy->cookie_name = strdup(defproxy.cookie_name);
2239 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002240 if (defproxy.cookie_domain)
2241 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002242
Willy Tarreau31936852010-10-06 16:59:56 +02002243 if (defproxy.cookie_maxidle)
2244 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2245
2246 if (defproxy.cookie_maxlife)
2247 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2248
Emeric Brun647caf12009-06-30 17:57:00 +02002249 if (defproxy.rdp_cookie_name)
2250 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2251 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2252
Willy Tarreau01732802007-11-01 22:48:15 +01002253 if (defproxy.url_param_name)
2254 curproxy->url_param_name = strdup(defproxy.url_param_name);
2255 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002256
Benoitaffb4812009-03-25 13:02:10 +01002257 if (defproxy.hh_name)
2258 curproxy->hh_name = strdup(defproxy.hh_name);
2259 curproxy->hh_len = defproxy.hh_len;
2260 curproxy->hh_match_domain = defproxy.hh_match_domain;
2261
Willy Tarreauef9a3602012-12-08 22:29:20 +01002262 if (defproxy.conn_src.iface_name)
2263 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2264 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002265 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002266#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002267 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002268#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002269 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002270
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002271 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002272 if (defproxy.capture_name)
2273 curproxy->capture_name = strdup(defproxy.capture_name);
2274 curproxy->capture_namelen = defproxy.capture_namelen;
2275 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002276 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002277
Willy Tarreau977b8e42006-12-29 14:19:17 +01002278 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002279 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002280 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002281 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002282 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002283 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002284 curproxy->mon_net = defproxy.mon_net;
2285 curproxy->mon_mask = defproxy.mon_mask;
2286 if (defproxy.monitor_uri)
2287 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2288 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002289 if (defproxy.defbe.name)
2290 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002291
2292 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002293 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2294 if (curproxy->conf.logformat_string &&
2295 curproxy->conf.logformat_string != default_http_log_format &&
2296 curproxy->conf.logformat_string != default_tcp_log_format &&
2297 curproxy->conf.logformat_string != clf_http_log_format)
2298 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2299
2300 if (defproxy.conf.lfs_file) {
2301 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2302 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2303 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002304 }
2305
2306 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002307 curproxy->timeout.connect = defproxy.timeout.connect;
2308 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002309 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002310 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002311 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002312 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002313 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002314 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002315 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002316 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002317 }
2318
Willy Tarreaubaaee002006-06-26 02:48:02 +02002319 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002320 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002321
2322 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002323 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002324 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002325 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002326 LIST_INIT(&node->list);
2327 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2328 }
2329
Willy Tarreau62a61232013-04-12 18:13:46 +02002330 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2331 if (curproxy->conf.uniqueid_format_string)
2332 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2333
Willy Tarreau094af4e2015-01-07 15:03:42 +01002334 if (defproxy.log_tag)
2335 curproxy->log_tag = strdup(defproxy.log_tag);
2336
Willy Tarreau62a61232013-04-12 18:13:46 +02002337 if (defproxy.conf.uif_file) {
2338 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2339 curproxy->conf.uif_line = defproxy.conf.uif_line;
2340 }
William Lallemanda73203e2012-03-12 12:48:57 +01002341
2342 /* copy default header unique id */
2343 if (defproxy.header_unique_id)
2344 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2345
William Lallemand82fe75c2012-10-23 10:25:10 +02002346 /* default compression options */
2347 if (defproxy.comp != NULL) {
2348 curproxy->comp = calloc(1, sizeof(struct comp));
2349 curproxy->comp->algos = defproxy.comp->algos;
2350 curproxy->comp->types = defproxy.comp->types;
2351 }
2352
Willy Tarreaubaaee002006-06-26 02:48:02 +02002353 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002354 curproxy->conf.used_listener_id = EB_ROOT;
2355 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002356
Simon Horman98637e52014-06-20 12:30:16 +09002357 if (defproxy.check_path)
2358 curproxy->check_path = strdup(defproxy.check_path);
2359 if (defproxy.check_command)
2360 curproxy->check_command = strdup(defproxy.check_command);
2361
Simon Horman9dc49962015-01-30 11:22:59 +09002362 if (defproxy.email_alert.mailers.name)
2363 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2364 if (defproxy.email_alert.from)
2365 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2366 if (defproxy.email_alert.to)
2367 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2368 if (defproxy.email_alert.myhostname)
2369 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002370 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002371
Willy Tarreau93893792009-07-23 13:19:11 +02002372 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 }
2374 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2375 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002376 /* FIXME-20070101: we should do this too at the end of the
2377 * config parsing to free all default values.
2378 */
Willy Tarreaua534fea2008-08-03 12:19:50 +02002379 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002380 free(defproxy.check_command);
2381 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002382 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002383 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002384 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002385 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002386 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002387 free(defproxy.capture_name);
2388 free(defproxy.monitor_uri);
2389 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002390 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002391 free(defproxy.fwdfor_hdr_name);
2392 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002393 free(defproxy.orgto_hdr_name);
2394 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002395 free(defproxy.server_id_hdr_name);
2396 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002397 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002398 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002399 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002400 free(defproxy.expect_regex);
2401 defproxy.expect_regex = NULL;
2402 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002403
Willy Tarreau62a61232013-04-12 18:13:46 +02002404 if (defproxy.conf.logformat_string != default_http_log_format &&
2405 defproxy.conf.logformat_string != default_tcp_log_format &&
2406 defproxy.conf.logformat_string != clf_http_log_format)
2407 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002408
Willy Tarreau62a61232013-04-12 18:13:46 +02002409 free(defproxy.conf.uniqueid_format_string);
2410 free(defproxy.conf.lfs_file);
2411 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002412 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002413 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002414
Willy Tarreaua534fea2008-08-03 12:19:50 +02002415 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002416 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002417
Willy Tarreaubaaee002006-06-26 02:48:02 +02002418 /* we cannot free uri_auth because it might already be used */
2419 init_default_instance();
2420 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002421 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2422 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002423 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002425 }
2426 else if (curproxy == NULL) {
2427 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002430 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002431
2432 /* update the current file and line being parsed */
2433 curproxy->conf.args.file = curproxy->conf.file;
2434 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002435
2436 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002437 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2438 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2439 if (err_code & ERR_FATAL)
2440 goto out;
2441 }
2442 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002443 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002444 int cur_arg;
2445
Willy Tarreaubaaee002006-06-26 02:48:02 +02002446 if (curproxy == &defproxy) {
2447 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002448 err_code |= ERR_ALERT | ERR_FATAL;
2449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002450 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002451 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002452 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002453
Willy Tarreau24709282013-03-10 21:32:12 +01002454 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002455 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002456 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002457 err_code |= ERR_ALERT | ERR_FATAL;
2458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002459 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002460
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002461 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002462
2463 /* use default settings for unix sockets */
2464 bind_conf->ux.uid = global.unix_bind.ux.uid;
2465 bind_conf->ux.gid = global.unix_bind.ux.gid;
2466 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002467
2468 /* NOTE: the following line might create several listeners if there
2469 * are comma-separated IPs or port ranges. So all further processing
2470 * will have to be applied to all listeners created after last_listen.
2471 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002472 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2473 if (errmsg && *errmsg) {
2474 indent_msg(&errmsg, 2);
2475 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002476 }
2477 else
2478 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2479 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002480 err_code |= ERR_ALERT | ERR_FATAL;
2481 goto out;
2482 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002483
Willy Tarreau4348fad2012-09-20 16:48:07 +02002484 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2485 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002486 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002487 }
2488
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002489 cur_arg = 2;
2490 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002491 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002492 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002493 char *err;
2494
Willy Tarreau26982662012-09-12 23:17:10 +02002495 kw = bind_find_kw(args[cur_arg]);
2496 if (kw) {
2497 char *err = NULL;
2498 int code;
2499
2500 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002501 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2502 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002503 cur_arg += 1 + kw->skip ;
2504 err_code |= ERR_ALERT | ERR_FATAL;
2505 goto out;
2506 }
2507
Willy Tarreau4348fad2012-09-20 16:48:07 +02002508 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002509 err_code |= code;
2510
2511 if (code) {
2512 if (err && *err) {
2513 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002514 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002515 }
2516 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002517 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2518 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002519 if (code & ERR_FATAL) {
2520 free(err);
2521 cur_arg += 1 + kw->skip;
2522 goto out;
2523 }
2524 }
2525 free(err);
2526 cur_arg += 1 + kw->skip;
2527 continue;
2528 }
2529
Willy Tarreau8638f482012-09-18 18:01:17 +02002530 err = NULL;
2531 if (!bind_dumped) {
2532 bind_dump_kws(&err);
2533 indent_msg(&err, 4);
2534 bind_dumped = 1;
2535 }
2536
2537 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2538 file, linenum, args[0], args[1], args[cur_arg],
2539 err ? " Registered keywords :" : "", err ? err : "");
2540 free(err);
2541
Willy Tarreau93893792009-07-23 13:19:11 +02002542 err_code |= ERR_ALERT | ERR_FATAL;
2543 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002544 }
Willy Tarreau93893792009-07-23 13:19:11 +02002545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002546 }
2547 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002548 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002549 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2550 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002551 err_code |= ERR_ALERT | ERR_FATAL;
2552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002554 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002555 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002556
Willy Tarreaubaaee002006-06-26 02:48:02 +02002557 /* flush useless bits */
2558 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002559 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002560 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002561 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002562 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002563 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002564
Willy Tarreau1c47f852006-07-09 08:22:27 +02002565 if (!*args[1]) {
2566 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2567 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002568 err_code |= ERR_ALERT | ERR_FATAL;
2569 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002570 }
2571
Willy Tarreaua534fea2008-08-03 12:19:50 +02002572 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002573 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002574 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002575 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002576 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2577
Willy Tarreau93893792009-07-23 13:19:11 +02002578 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
2581 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2582 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2583 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2584 else {
2585 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002586 err_code |= ERR_ALERT | ERR_FATAL;
2587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002588 }
2589 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002590 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002591 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002592
2593 if (curproxy == &defproxy) {
2594 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2595 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002596 err_code |= ERR_ALERT | ERR_FATAL;
2597 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002598 }
2599
2600 if (!*args[1]) {
2601 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002605 }
2606
2607 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002608 curproxy->conf.id.key = curproxy->uuid;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002609
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002610 if (curproxy->uuid <= 0) {
2611 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002612 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002613 err_code |= ERR_ALERT | ERR_FATAL;
2614 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002615 }
2616
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002617 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2618 if (node) {
2619 struct proxy *target = container_of(node, struct proxy, conf.id);
2620 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2621 file, linenum, proxy_type_str(curproxy), curproxy->id,
2622 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2623 err_code |= ERR_ALERT | ERR_FATAL;
2624 goto out;
2625 }
2626 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002627 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002628 else if (!strcmp(args[0], "description")) {
2629 int i, len=0;
2630 char *d;
2631
Cyril Bonté99ed3272010-01-24 23:29:44 +01002632 if (curproxy == &defproxy) {
2633 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2634 file, linenum, args[0]);
2635 err_code |= ERR_ALERT | ERR_FATAL;
2636 goto out;
2637 }
2638
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002639 if (!*args[1]) {
2640 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2641 file, linenum, args[0]);
2642 return -1;
2643 }
2644
Willy Tarreau348acfe2014-04-14 15:00:39 +02002645 for (i = 1; *args[i]; i++)
2646 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002647
2648 d = (char *)calloc(1, len);
2649 curproxy->desc = d;
2650
Willy Tarreau348acfe2014-04-14 15:00:39 +02002651 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2652 for (i = 2; *args[i]; i++)
2653 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002654
2655 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002656 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
2657 curproxy->state = PR_STSTOPPED;
2658 }
2659 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
2660 curproxy->state = PR_STNEW;
2661 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002662 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2663 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002664 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002665
2666 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002667 unsigned int low, high;
2668
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002669 if (strcmp(args[cur_arg], "all") == 0) {
2670 set = 0;
2671 break;
2672 }
2673 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002674 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002675 }
2676 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002677 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002678 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002679 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002680 char *dash = strchr(args[cur_arg], '-');
2681
2682 low = high = str2uic(args[cur_arg]);
2683 if (dash)
2684 high = str2uic(dash + 1);
2685
2686 if (high < low) {
2687 unsigned int swap = low;
2688 low = high;
2689 high = swap;
2690 }
2691
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002692 if (low < 1 || high > LONGBITS) {
2693 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2694 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002695 err_code |= ERR_ALERT | ERR_FATAL;
2696 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002697 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002698 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002699 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002700 }
2701 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002702 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2703 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002704 err_code |= ERR_ALERT | ERR_FATAL;
2705 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002706 }
2707 cur_arg++;
2708 }
2709 curproxy->bind_proc = set;
2710 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002711 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002712 if (curproxy == &defproxy) {
2713 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002714 err_code |= ERR_ALERT | ERR_FATAL;
2715 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002716 }
2717
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002718 err = invalid_char(args[1]);
2719 if (err) {
2720 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2721 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002722 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002723 }
2724
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002725 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002726 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2727 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
2729 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002730 }
2731 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2733 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002734
Willy Tarreau977b8e42006-12-29 14:19:17 +01002735 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002736 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002737
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 if (*(args[1]) == 0) {
2739 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2740 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002741 err_code |= ERR_ALERT | ERR_FATAL;
2742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002744
Willy Tarreau67402132012-05-31 20:40:20 +02002745 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002746 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002747 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002748 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002749 curproxy->cookie_name = strdup(args[1]);
2750 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002751
Willy Tarreaubaaee002006-06-26 02:48:02 +02002752 cur_arg = 2;
2753 while (*(args[cur_arg])) {
2754 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002755 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 }
2757 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002758 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 }
2760 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002761 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 }
2763 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002764 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002765 }
2766 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002767 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002768 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002769 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002770 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002771 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002772 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002773 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02002775 else if (!strcmp(args[cur_arg], "httponly")) {
2776 curproxy->ck_opts |= PR_CK_HTTPONLY;
2777 }
2778 else if (!strcmp(args[cur_arg], "secure")) {
2779 curproxy->ck_opts |= PR_CK_SECURE;
2780 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002781 else if (!strcmp(args[cur_arg], "domain")) {
2782 if (!*args[cur_arg + 1]) {
2783 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
2784 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02002785 err_code |= ERR_ALERT | ERR_FATAL;
2786 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002787 }
2788
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002789 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002790 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002791 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
2792 " dots nor does not start with a dot."
2793 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002794 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01002795 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002796 }
2797
2798 err = invalid_domainchar(args[cur_arg + 1]);
2799 if (err) {
2800 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
2801 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002802 err_code |= ERR_ALERT | ERR_FATAL;
2803 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002804 }
2805
Willy Tarreau68a897b2009-12-03 23:28:34 +01002806 if (!curproxy->cookie_domain) {
2807 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
2808 } else {
2809 /* one domain was already specified, add another one by
2810 * building the string which will be returned along with
2811 * the cookie.
2812 */
2813 char *new_ptr;
2814 int new_len = strlen(curproxy->cookie_domain) +
2815 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
2816 new_ptr = malloc(new_len);
2817 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
2818 free(curproxy->cookie_domain);
2819 curproxy->cookie_domain = new_ptr;
2820 }
Willy Tarreau31936852010-10-06 16:59:56 +02002821 cur_arg++;
2822 }
2823 else if (!strcmp(args[cur_arg], "maxidle")) {
2824 unsigned int maxidle;
2825 const char *res;
2826
2827 if (!*args[cur_arg + 1]) {
2828 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
2829 file, linenum, args[cur_arg]);
2830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
2832 }
2833
2834 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
2835 if (res) {
2836 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2837 file, linenum, *res, args[cur_arg]);
2838 err_code |= ERR_ALERT | ERR_FATAL;
2839 goto out;
2840 }
2841 curproxy->cookie_maxidle = maxidle;
2842 cur_arg++;
2843 }
2844 else if (!strcmp(args[cur_arg], "maxlife")) {
2845 unsigned int maxlife;
2846 const char *res;
2847
2848 if (!*args[cur_arg + 1]) {
2849 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
2850 file, linenum, args[cur_arg]);
2851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
2853 }
2854
2855 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
2856 if (res) {
2857 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2858 file, linenum, *res, args[cur_arg]);
2859 err_code |= ERR_ALERT | ERR_FATAL;
2860 goto out;
2861 }
2862 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02002863 cur_arg++;
2864 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002865 else {
Willy Tarreau31936852010-10-06 16:59:56 +02002866 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 +02002867 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002868 err_code |= ERR_ALERT | ERR_FATAL;
2869 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 }
2871 cur_arg++;
2872 }
Willy Tarreau67402132012-05-31 20:40:20 +02002873 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002874 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
2875 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002876 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002877 }
2878
Willy Tarreau67402132012-05-31 20:40:20 +02002879 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
2881 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002882 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002883 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002884
Willy Tarreau67402132012-05-31 20:40:20 +02002885 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02002886 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
2887 file, linenum);
2888 err_code |= ERR_ALERT | ERR_FATAL;
2889 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002890 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09002891 else if (!strcmp(args[0], "email-alert")) {
2892 if (*(args[1]) == 0) {
2893 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2894 file, linenum, args[0]);
2895 err_code |= ERR_ALERT | ERR_FATAL;
2896 goto out;
2897 }
2898
2899 if (!strcmp(args[1], "from")) {
2900 if (*(args[1]) == 0) {
2901 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2902 file, linenum, args[1]);
2903 err_code |= ERR_ALERT | ERR_FATAL;
2904 goto out;
2905 }
2906 free(curproxy->email_alert.from);
2907 curproxy->email_alert.from = strdup(args[2]);
2908 }
2909 else if (!strcmp(args[1], "mailers")) {
2910 if (*(args[1]) == 0) {
2911 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2912 file, linenum, args[1]);
2913 err_code |= ERR_ALERT | ERR_FATAL;
2914 goto out;
2915 }
2916 free(curproxy->email_alert.mailers.name);
2917 curproxy->email_alert.mailers.name = strdup(args[2]);
2918 }
2919 else if (!strcmp(args[1], "myhostname")) {
2920 if (*(args[1]) == 0) {
2921 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2922 file, linenum, args[1]);
2923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
2925 }
2926 free(curproxy->email_alert.myhostname);
2927 curproxy->email_alert.myhostname = strdup(args[2]);
2928 }
Simon Horman64e34162015-02-06 11:11:57 +09002929 else if (!strcmp(args[1], "level")) {
2930 curproxy->email_alert.level = get_log_level(args[2]);
2931 if (curproxy->email_alert.level < 0) {
2932 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
2933 file, linenum, args[1], args[2]);
2934 err_code |= ERR_ALERT | ERR_FATAL;
2935 goto out;
2936 }
2937 }
Simon Horman9dc49962015-01-30 11:22:59 +09002938 else if (!strcmp(args[1], "to")) {
2939 if (*(args[1]) == 0) {
2940 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2941 file, linenum, args[1]);
2942 err_code |= ERR_ALERT | ERR_FATAL;
2943 goto out;
2944 }
2945 free(curproxy->email_alert.to);
2946 curproxy->email_alert.to = strdup(args[2]);
2947 }
2948 else {
2949 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
2950 file, linenum, args[1]);
2951 err_code |= ERR_ALERT | ERR_FATAL;
2952 goto out;
2953 }
Simon Horman64e34162015-02-06 11:11:57 +09002954 /* Indicate that the email_alert is at least partially configured */
2955 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09002956 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09002957 else if (!strcmp(args[0], "external-check")) {
2958 if (*(args[1]) == 0) {
2959 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2960 file, linenum, args[0]);
2961 err_code |= ERR_ALERT | ERR_FATAL;
2962 goto out;
2963 }
2964
2965 if (!strcmp(args[1], "command")) {
2966 if (*(args[1]) == 0) {
2967 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2968 file, linenum, args[1]);
2969 err_code |= ERR_ALERT | ERR_FATAL;
2970 goto out;
2971 }
2972 free(curproxy->check_command);
2973 curproxy->check_command = strdup(args[2]);
2974 }
2975 else if (!strcmp(args[1], "path")) {
2976 if (*(args[1]) == 0) {
2977 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
2978 file, linenum, args[1]);
2979 err_code |= ERR_ALERT | ERR_FATAL;
2980 goto out;
2981 }
2982 free(curproxy->check_path);
2983 curproxy->check_path = strdup(args[2]);
2984 }
2985 else {
2986 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
2987 file, linenum, args[1]);
2988 err_code |= ERR_ALERT | ERR_FATAL;
2989 goto out;
2990 }
2991 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02002992 else if (!strcmp(args[0], "persist")) { /* persist */
2993 if (*(args[1]) == 0) {
2994 Alert("parsing [%s:%d] : missing persist method.\n",
2995 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002996 err_code |= ERR_ALERT | ERR_FATAL;
2997 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02002998 }
2999
3000 if (!strncmp(args[1], "rdp-cookie", 10)) {
3001 curproxy->options2 |= PR_O2_RDPC_PRST;
3002
Emeric Brunb982a3d2010-01-04 15:45:53 +01003003 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003004 const char *beg, *end;
3005
3006 beg = args[1] + 11;
3007 end = strchr(beg, ')');
3008
3009 if (!end || end == beg) {
3010 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3011 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003012 err_code |= ERR_ALERT | ERR_FATAL;
3013 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003014 }
3015
3016 free(curproxy->rdp_cookie_name);
3017 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3018 curproxy->rdp_cookie_len = end-beg;
3019 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003020 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003021 free(curproxy->rdp_cookie_name);
3022 curproxy->rdp_cookie_name = strdup("msts");
3023 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3024 }
3025 else { /* syntax */
3026 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3027 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003028 err_code |= ERR_ALERT | ERR_FATAL;
3029 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003030 }
3031 }
3032 else {
3033 Alert("parsing [%s:%d] : unknown persist method.\n",
3034 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003035 err_code |= ERR_ALERT | ERR_FATAL;
3036 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003037 }
3038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003039 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003040 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003042 if (curproxy == &defproxy) {
3043 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
3046 }
3047
Willy Tarreau977b8e42006-12-29 14:19:17 +01003048 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003049 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003050
Willy Tarreaubaaee002006-06-26 02:48:02 +02003051 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003052 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003053 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_ALERT | ERR_FATAL;
3055 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003056 }
3057 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003058 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003059 curproxy->appsession_name = strdup(args[1]);
3060 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3061 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003062 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3063 if (err) {
3064 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3065 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003066 err_code |= ERR_ALERT | ERR_FATAL;
3067 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003068 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003069 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003070
Willy Tarreau51041c72007-09-09 21:56:53 +02003071 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3072 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003073 err_code |= ERR_ALERT | ERR_ABORT;
3074 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003075 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003076
3077 cur_arg = 6;
3078 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003079 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3080 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003081 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003082 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003083 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003084 } else if (!strcmp(args[cur_arg], "prefix")) {
3085 curproxy->options2 |= PR_O2_AS_PFX;
3086 } else if (!strcmp(args[cur_arg], "mode")) {
3087 if (!*args[cur_arg + 1]) {
3088 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3089 file, linenum, args[0], args[cur_arg]);
3090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
3092 }
3093
3094 cur_arg++;
3095 if (!strcmp(args[cur_arg], "query-string")) {
3096 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3097 curproxy->options2 |= PR_O2_AS_M_QS;
3098 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3099 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3100 curproxy->options2 |= PR_O2_AS_M_PP;
3101 } else {
3102 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3103 err_code |= ERR_ALERT | ERR_FATAL;
3104 goto out;
3105 }
3106 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003107 cur_arg++;
3108 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003109 } /* Url App Session */
3110 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003111 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003112 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003113
Willy Tarreaubaaee002006-06-26 02:48:02 +02003114 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003115 if (curproxy == &defproxy) {
3116 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3117 err_code |= ERR_ALERT | ERR_FATAL;
3118 goto out;
3119 }
3120
Willy Tarreaubaaee002006-06-26 02:48:02 +02003121 if (*(args[4]) == 0) {
3122 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3123 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_FATAL;
3125 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003126 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003127 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003128 curproxy->capture_name = strdup(args[2]);
3129 curproxy->capture_namelen = strlen(curproxy->capture_name);
3130 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 curproxy->to_log |= LW_COOKIE;
3132 }
3133 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3134 struct cap_hdr *hdr;
3135
3136 if (curproxy == &defproxy) {
3137 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 +02003138 err_code |= ERR_ALERT | ERR_FATAL;
3139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003140 }
3141
3142 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3143 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3144 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003147 }
3148
3149 hdr = calloc(sizeof(struct cap_hdr), 1);
3150 hdr->next = curproxy->req_cap;
3151 hdr->name = strdup(args[3]);
3152 hdr->namelen = strlen(args[3]);
3153 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003154 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 hdr->index = curproxy->nb_req_cap++;
3156 curproxy->req_cap = hdr;
3157 curproxy->to_log |= LW_REQHDR;
3158 }
3159 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3160 struct cap_hdr *hdr;
3161
3162 if (curproxy == &defproxy) {
3163 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 +02003164 err_code |= ERR_ALERT | ERR_FATAL;
3165 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 }
3167
3168 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3169 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3170 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003173 }
3174 hdr = calloc(sizeof(struct cap_hdr), 1);
3175 hdr->next = curproxy->rsp_cap;
3176 hdr->name = strdup(args[3]);
3177 hdr->namelen = strlen(args[3]);
3178 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003179 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 hdr->index = curproxy->nb_rsp_cap++;
3181 curproxy->rsp_cap = hdr;
3182 curproxy->to_log |= LW_RSPHDR;
3183 }
3184 else {
3185 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3186 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003187 err_code |= ERR_ALERT | ERR_FATAL;
3188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 }
3190 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003191 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003192 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003193 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003194
Willy Tarreaubaaee002006-06-26 02:48:02 +02003195 if (*(args[1]) == 0) {
3196 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3197 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003198 err_code |= ERR_ALERT | ERR_FATAL;
3199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 }
3201 curproxy->conn_retries = atol(args[1]);
3202 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003203 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003204 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003205
3206 if (curproxy == &defproxy) {
3207 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3208 err_code |= ERR_ALERT | ERR_FATAL;
3209 goto out;
3210 }
3211
Willy Tarreau20b0de52012-12-24 15:45:22 +01003212 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3213 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3214 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3215 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003216 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003217 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3218 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 +01003219 file, linenum, args[0]);
3220 err_code |= ERR_WARN;
3221 }
3222
Willy Tarreauff011f22011-01-06 17:51:27 +01003223 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003224
Willy Tarreauff011f22011-01-06 17:51:27 +01003225 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003226 err_code |= ERR_ALERT | ERR_ABORT;
3227 goto out;
3228 }
3229
Willy Tarreau5002f572014-04-23 01:32:02 +02003230 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003231 err_code |= warnif_cond_conflicts(rule->cond,
3232 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3233 file, linenum);
3234
Willy Tarreauff011f22011-01-06 17:51:27 +01003235 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003236 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003237 else if (!strcmp(args[0], "http-response")) { /* response access control */
3238 struct http_res_rule *rule;
3239
3240 if (curproxy == &defproxy) {
3241 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
3244 }
3245
3246 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3247 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3248 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3249 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3250 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3251 file, linenum, args[0]);
3252 err_code |= ERR_WARN;
3253 }
3254
3255 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3256
3257 if (!rule) {
3258 err_code |= ERR_ALERT | ERR_ABORT;
3259 goto out;
3260 }
3261
3262 err_code |= warnif_cond_conflicts(rule->cond,
3263 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3264 file, linenum);
3265
3266 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3267 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003268 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3269 /* set the header name and length into the proxy structure */
3270 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3271 err_code |= ERR_WARN;
3272
3273 if (!*args[1]) {
3274 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3275 file, linenum, args[0]);
3276 err_code |= ERR_ALERT | ERR_FATAL;
3277 goto out;
3278 }
3279
3280 /* set the desired header name */
3281 free(curproxy->server_id_hdr_name);
3282 curproxy->server_id_hdr_name = strdup(args[1]);
3283 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3284 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003285 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003286 struct http_req_rule *rule;
3287
Willy Tarreaub099aca2008-10-12 17:26:37 +02003288 if (curproxy == &defproxy) {
3289 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003290 err_code |= ERR_ALERT | ERR_FATAL;
3291 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003292 }
3293
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003294 /* emulate "block" using "http-request block". Since these rules are supposed to
3295 * be processed before all http-request rules, we put them into their own list
3296 * and will insert them at the end.
3297 */
3298 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3299 if (!rule) {
3300 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003301 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003302 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003303 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3304 err_code |= warnif_cond_conflicts(rule->cond,
3305 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3306 file, linenum);
3307 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003308
3309 if (!already_warned(WARN_BLOCK_DEPRECATED))
3310 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]);
3311
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003312 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003313 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003314 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003315
Cyril Bonté99ed3272010-01-24 23:29:44 +01003316 if (curproxy == &defproxy) {
3317 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3318 err_code |= ERR_ALERT | ERR_FATAL;
3319 goto out;
3320 }
3321
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +01003322 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003323 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3324 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003325 err_code |= ERR_ALERT | ERR_FATAL;
3326 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003327 }
3328
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003329 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003330 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003331 err_code |= warnif_cond_conflicts(rule->cond,
3332 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3333 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003334 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003335 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003336 struct switching_rule *rule;
3337
Willy Tarreaub099aca2008-10-12 17:26:37 +02003338 if (curproxy == &defproxy) {
3339 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003340 err_code |= ERR_ALERT | ERR_FATAL;
3341 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003342 }
3343
Willy Tarreau55ea7572007-06-17 19:56:27 +02003344 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003345 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003346
3347 if (*(args[1]) == 0) {
3348 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003349 err_code |= ERR_ALERT | ERR_FATAL;
3350 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003351 }
3352
Willy Tarreauf51658d2014-04-23 01:21:56 +02003353 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3354 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3355 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3356 file, linenum, errmsg);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003360
Willy Tarreauf51658d2014-04-23 01:21:56 +02003361 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003362 }
3363
3364 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3365 rule->cond = cond;
3366 rule->be.name = strdup(args[1]);
3367 LIST_INIT(&rule->list);
3368 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3369 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003370 else if (strcmp(args[0], "use-server") == 0) {
3371 struct server_rule *rule;
3372
3373 if (curproxy == &defproxy) {
3374 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3375 err_code |= ERR_ALERT | ERR_FATAL;
3376 goto out;
3377 }
3378
3379 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3380 err_code |= ERR_WARN;
3381
3382 if (*(args[1]) == 0) {
3383 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3384 err_code |= ERR_ALERT | ERR_FATAL;
3385 goto out;
3386 }
3387
3388 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3389 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3390 file, linenum, args[0]);
3391 err_code |= ERR_ALERT | ERR_FATAL;
3392 goto out;
3393 }
3394
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003395 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3396 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3397 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003398 err_code |= ERR_ALERT | ERR_FATAL;
3399 goto out;
3400 }
3401
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003402 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003403
3404 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3405 rule->cond = cond;
3406 rule->srv.name = strdup(args[1]);
3407 LIST_INIT(&rule->list);
3408 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3409 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3410 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003411 else if ((!strcmp(args[0], "force-persist")) ||
3412 (!strcmp(args[0], "ignore-persist"))) {
3413 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003414
3415 if (curproxy == &defproxy) {
3416 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3417 err_code |= ERR_ALERT | ERR_FATAL;
3418 goto out;
3419 }
3420
3421 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3422 err_code |= ERR_WARN;
3423
Willy Tarreauef6494c2010-01-28 17:12:36 +01003424 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003425 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3426 file, linenum, args[0]);
3427 err_code |= ERR_ALERT | ERR_FATAL;
3428 goto out;
3429 }
3430
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003431 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3432 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3433 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
3437
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003438 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3439 * where force-persist is applied.
3440 */
3441 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003442
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003443 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003444 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003445 if (!strcmp(args[0], "force-persist")) {
3446 rule->type = PERSIST_TYPE_FORCE;
3447 } else {
3448 rule->type = PERSIST_TYPE_IGNORE;
3449 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003450 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003451 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003452 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003453 else if (!strcmp(args[0], "stick-table")) {
3454 int myidx = 1;
3455
Emeric Brun32da3c42010-09-23 18:39:19 +02003456 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003457 curproxy->table.type = (unsigned int)-1;
3458 while (*args[myidx]) {
3459 const char *err;
3460
3461 if (strcmp(args[myidx], "size") == 0) {
3462 myidx++;
3463 if (!*(args[myidx])) {
3464 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3465 file, linenum, args[myidx-1]);
3466 err_code |= ERR_ALERT | ERR_FATAL;
3467 goto out;
3468 }
3469 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3470 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3471 file, linenum, *err, args[myidx-1]);
3472 err_code |= ERR_ALERT | ERR_FATAL;
3473 goto out;
3474 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003475 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003476 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003477 else if (strcmp(args[myidx], "peers") == 0) {
3478 myidx++;
Godbach50523162013-12-11 19:48:57 +08003479 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003480 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3481 file, linenum, args[myidx-1]);
3482 err_code |= ERR_ALERT | ERR_FATAL;
3483 goto out;
Godbach50523162013-12-11 19:48:57 +08003484 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003485 curproxy->table.peers.name = strdup(args[myidx++]);
3486 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003487 else if (strcmp(args[myidx], "expire") == 0) {
3488 myidx++;
3489 if (!*(args[myidx])) {
3490 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3491 file, linenum, args[myidx-1]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
3495 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3496 if (err) {
3497 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3498 file, linenum, *err, args[myidx-1]);
3499 err_code |= ERR_ALERT | ERR_FATAL;
3500 goto out;
3501 }
3502 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003503 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003504 }
3505 else if (strcmp(args[myidx], "nopurge") == 0) {
3506 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003507 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003508 }
3509 else if (strcmp(args[myidx], "type") == 0) {
3510 myidx++;
3511 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3512 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3513 file, linenum, args[myidx]);
3514 err_code |= ERR_ALERT | ERR_FATAL;
3515 goto out;
3516 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003517 /* myidx already points to next arg */
3518 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003519 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003520 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003521 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003522
3523 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003524 nw = args[myidx];
3525 while (*nw) {
3526 /* the "store" keyword supports a comma-separated list */
3527 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003528 sa = NULL; /* store arg */
3529 while (*nw && *nw != ',') {
3530 if (*nw == '(') {
3531 *nw = 0;
3532 sa = ++nw;
3533 while (*nw != ')') {
3534 if (!*nw) {
3535 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3536 file, linenum, args[0], cw);
3537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
3539 }
3540 nw++;
3541 }
3542 *nw = '\0';
3543 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003544 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003545 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003546 if (*nw)
3547 *nw++ = '\0';
3548 type = stktable_get_data_type(cw);
3549 if (type < 0) {
3550 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3551 file, linenum, args[0], cw);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
3554 }
Willy Tarreauac782882010-06-20 10:41:54 +02003555
3556 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3557 switch (err) {
3558 case PE_NONE: break;
3559 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003560 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3561 file, linenum, args[0], cw);
3562 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003563 break;
3564
3565 case PE_ARG_MISSING:
3566 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3567 file, linenum, args[0], cw);
3568 err_code |= ERR_ALERT | ERR_FATAL;
3569 goto out;
3570
3571 case PE_ARG_NOT_USED:
3572 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3573 file, linenum, args[0], cw);
3574 err_code |= ERR_ALERT | ERR_FATAL;
3575 goto out;
3576
3577 default:
3578 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3579 file, linenum, args[0], cw);
3580 err_code |= ERR_ALERT | ERR_FATAL;
3581 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003582 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003583 }
3584 myidx++;
3585 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003586 else {
3587 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3588 file, linenum, args[myidx]);
3589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003591 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003592 }
3593
3594 if (!curproxy->table.size) {
3595 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3596 file, linenum);
3597 err_code |= ERR_ALERT | ERR_FATAL;
3598 goto out;
3599 }
3600
3601 if (curproxy->table.type == (unsigned int)-1) {
3602 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3603 file, linenum);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607 }
3608 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003609 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003610 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003611 int myidx = 0;
3612 const char *name = NULL;
3613 int flags;
3614
3615 if (curproxy == &defproxy) {
3616 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
3619 }
3620
3621 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3622 err_code |= ERR_WARN;
3623 goto out;
3624 }
3625
3626 myidx++;
3627 if ((strcmp(args[myidx], "store") == 0) ||
3628 (strcmp(args[myidx], "store-request") == 0)) {
3629 myidx++;
3630 flags = STK_IS_STORE;
3631 }
3632 else if (strcmp(args[myidx], "store-response") == 0) {
3633 myidx++;
3634 flags = STK_IS_STORE | STK_ON_RSP;
3635 }
3636 else if (strcmp(args[myidx], "match") == 0) {
3637 myidx++;
3638 flags = STK_IS_MATCH;
3639 }
3640 else if (strcmp(args[myidx], "on") == 0) {
3641 myidx++;
3642 flags = STK_IS_MATCH | STK_IS_STORE;
3643 }
3644 else {
3645 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3646 err_code |= ERR_ALERT | ERR_FATAL;
3647 goto out;
3648 }
3649
3650 if (*(args[myidx]) == 0) {
3651 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
3654 }
3655
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003656 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003657 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003658 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003659 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003660 err_code |= ERR_ALERT | ERR_FATAL;
3661 goto out;
3662 }
3663
3664 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003665 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3666 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3667 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003668 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003669 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003670 goto out;
3671 }
3672 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003673 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3674 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3675 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003676 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003677 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003678 goto out;
3679 }
3680 }
3681
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003682 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003683 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003684
Emeric Brunb982a3d2010-01-04 15:45:53 +01003685 if (strcmp(args[myidx], "table") == 0) {
3686 myidx++;
3687 name = args[myidx++];
3688 }
3689
Willy Tarreauef6494c2010-01-28 17:12:36 +01003690 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003691 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3692 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3693 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003694 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003695 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003696 goto out;
3697 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003698 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003699 else if (*(args[myidx])) {
3700 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3701 file, linenum, args[0], args[myidx]);
3702 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003703 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003704 goto out;
3705 }
Emeric Brun97679e72010-09-23 17:56:44 +02003706 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003707 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003708 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003709 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003710
Emeric Brunb982a3d2010-01-04 15:45:53 +01003711 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3712 rule->cond = cond;
3713 rule->expr = expr;
3714 rule->flags = flags;
3715 rule->table.name = name ? strdup(name) : NULL;
3716 LIST_INIT(&rule->list);
3717 if (flags & STK_ON_RSP)
3718 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3719 else
3720 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003722 else if (!strcmp(args[0], "stats")) {
3723 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3724 curproxy->uri_auth = NULL; /* we must detach from the default config */
3725
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003726 if (!*args[1]) {
3727 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003728 } else if (!strcmp(args[1], "admin")) {
3729 struct stats_admin_rule *rule;
3730
3731 if (curproxy == &defproxy) {
3732 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3733 err_code |= ERR_ALERT | ERR_FATAL;
3734 goto out;
3735 }
3736
3737 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3738 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3739 err_code |= ERR_ALERT | ERR_ABORT;
3740 goto out;
3741 }
3742
3743 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3744 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
3745 file, linenum, args[0], args[1]);
3746 err_code |= ERR_ALERT | ERR_FATAL;
3747 goto out;
3748 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003749 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3750 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
3751 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02003752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
3754 }
3755
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003756 err_code |= warnif_cond_conflicts(cond,
3757 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3758 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02003759
3760 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
3761 rule->cond = cond;
3762 LIST_INIT(&rule->list);
3763 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003764 } else if (!strcmp(args[1], "uri")) {
3765 if (*(args[2]) == 0) {
3766 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003767 err_code |= ERR_ALERT | ERR_FATAL;
3768 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003769 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
3770 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003771 err_code |= ERR_ALERT | ERR_ABORT;
3772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003773 }
3774 } else if (!strcmp(args[1], "realm")) {
3775 if (*(args[2]) == 0) {
3776 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
3780 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003781 err_code |= ERR_ALERT | ERR_ABORT;
3782 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003783 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02003784 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003785 unsigned interval;
3786
3787 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
3788 if (err) {
3789 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
3790 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02003791 err_code |= ERR_ALERT | ERR_FATAL;
3792 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003793 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
3794 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003795 err_code |= ERR_ALERT | ERR_ABORT;
3796 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02003797 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003798 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003799 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003800
3801 if (curproxy == &defproxy) {
3802 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806
3807 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3808 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3809 err_code |= ERR_ALERT | ERR_ABORT;
3810 goto out;
3811 }
3812
Willy Tarreauff011f22011-01-06 17:51:27 +01003813 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
3814 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003815 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
3816 file, linenum, args[0]);
3817 err_code |= ERR_WARN;
3818 }
3819
Willy Tarreauff011f22011-01-06 17:51:27 +01003820 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003821
Willy Tarreauff011f22011-01-06 17:51:27 +01003822 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003823 err_code |= ERR_ALERT | ERR_ABORT;
3824 goto out;
3825 }
3826
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003827 err_code |= warnif_cond_conflicts(rule->cond,
3828 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3829 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01003830 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01003831
Willy Tarreaubaaee002006-06-26 02:48:02 +02003832 } else if (!strcmp(args[1], "auth")) {
3833 if (*(args[2]) == 0) {
3834 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003835 err_code |= ERR_ALERT | ERR_FATAL;
3836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003837 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
3838 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003839 err_code |= ERR_ALERT | ERR_ABORT;
3840 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003841 }
3842 } else if (!strcmp(args[1], "scope")) {
3843 if (*(args[2]) == 0) {
3844 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003847 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
3848 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003849 err_code |= ERR_ALERT | ERR_ABORT;
3850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003851 }
3852 } else if (!strcmp(args[1], "enable")) {
3853 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
3854 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003855 err_code |= ERR_ALERT | ERR_ABORT;
3856 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003857 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003858 } else if (!strcmp(args[1], "hide-version")) {
3859 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
3860 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003861 err_code |= ERR_ALERT | ERR_ABORT;
3862 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02003863 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01003864 } else if (!strcmp(args[1], "show-legends")) {
3865 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
3866 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3867 err_code |= ERR_ALERT | ERR_ABORT;
3868 goto out;
3869 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003870 } else if (!strcmp(args[1], "show-node")) {
3871
3872 if (*args[2]) {
3873 int i;
3874 char c;
3875
3876 for (i=0; args[2][i]; i++) {
3877 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01003878 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
3879 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003880 break;
3881 }
3882
3883 if (!i || args[2][i]) {
3884 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
3885 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
3886 file, linenum, args[0], args[1]);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
3890 }
3891
3892 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
3893 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3894 err_code |= ERR_ALERT | ERR_ABORT;
3895 goto out;
3896 }
3897 } else if (!strcmp(args[1], "show-desc")) {
3898 char *desc = NULL;
3899
3900 if (*args[2]) {
3901 int i, len=0;
3902 char *d;
3903
Willy Tarreau348acfe2014-04-14 15:00:39 +02003904 for (i = 2; *args[i]; i++)
3905 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003906
3907 desc = d = (char *)calloc(1, len);
3908
Willy Tarreau348acfe2014-04-14 15:00:39 +02003909 d += snprintf(d, desc + len - d, "%s", args[2]);
3910 for (i = 3; *args[i]; i++)
3911 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003912 }
3913
3914 if (!*args[2] && !global.desc)
3915 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
3916 file, linenum, args[1]);
3917 else {
3918 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
3919 free(desc);
3920 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
3921 err_code |= ERR_ALERT | ERR_ABORT;
3922 goto out;
3923 }
3924 free(desc);
3925 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003926 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003927stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02003928 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 +01003929 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003932 }
3933 }
3934 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01003935 int optnum;
3936
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003937 if (*(args[1]) == '\0') {
3938 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
3939 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003940 err_code |= ERR_ALERT | ERR_FATAL;
3941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003942 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01003943
3944 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
3945 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003946 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
3947 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3948 file, linenum, cfg_opts[optnum].name);
3949 err_code |= ERR_ALERT | ERR_FATAL;
3950 goto out;
3951 }
Willy Tarreau93893792009-07-23 13:19:11 +02003952 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
3953 err_code |= ERR_WARN;
3954 goto out;
3955 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003956
Willy Tarreau3842f002009-06-14 11:39:52 +02003957 curproxy->no_options &= ~cfg_opts[optnum].val;
3958 curproxy->options &= ~cfg_opts[optnum].val;
3959
3960 switch (kwm) {
3961 case KWM_STD:
3962 curproxy->options |= cfg_opts[optnum].val;
3963 break;
3964 case KWM_NO:
3965 curproxy->no_options |= cfg_opts[optnum].val;
3966 break;
3967 case KWM_DEF: /* already cleared */
3968 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02003969 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01003970
Willy Tarreau93893792009-07-23 13:19:11 +02003971 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01003972 }
3973 }
3974
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003975 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
3976 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01003977 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
3978 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
3979 file, linenum, cfg_opts2[optnum].name);
3980 err_code |= ERR_ALERT | ERR_FATAL;
3981 goto out;
3982 }
Willy Tarreau93893792009-07-23 13:19:11 +02003983 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
3984 err_code |= ERR_WARN;
3985 goto out;
3986 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01003987
Willy Tarreau3842f002009-06-14 11:39:52 +02003988 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
3989 curproxy->options2 &= ~cfg_opts2[optnum].val;
3990
3991 switch (kwm) {
3992 case KWM_STD:
3993 curproxy->options2 |= cfg_opts2[optnum].val;
3994 break;
3995 case KWM_NO:
3996 curproxy->no_options2 |= cfg_opts2[optnum].val;
3997 break;
3998 case KWM_DEF: /* already cleared */
3999 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004000 }
Willy Tarreau93893792009-07-23 13:19:11 +02004001 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004002 }
4003 }
4004
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004005 /* HTTP options override each other. They can be cancelled using
4006 * "no option xxx" which only switches to default mode if the mode
4007 * was this one (useful for cancelling options set in defaults
4008 * sections).
4009 */
4010 if (strcmp(args[1], "httpclose") == 0) {
4011 if (kwm == KWM_STD) {
4012 curproxy->options &= ~PR_O_HTTP_MODE;
4013 curproxy->options |= PR_O_HTTP_PCL;
4014 goto out;
4015 }
4016 else if (kwm == KWM_NO) {
4017 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4018 curproxy->options &= ~PR_O_HTTP_MODE;
4019 goto out;
4020 }
4021 }
4022 else if (strcmp(args[1], "forceclose") == 0) {
4023 if (kwm == KWM_STD) {
4024 curproxy->options &= ~PR_O_HTTP_MODE;
4025 curproxy->options |= PR_O_HTTP_FCL;
4026 goto out;
4027 }
4028 else if (kwm == KWM_NO) {
4029 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4030 curproxy->options &= ~PR_O_HTTP_MODE;
4031 goto out;
4032 }
4033 }
4034 else if (strcmp(args[1], "http-server-close") == 0) {
4035 if (kwm == KWM_STD) {
4036 curproxy->options &= ~PR_O_HTTP_MODE;
4037 curproxy->options |= PR_O_HTTP_SCL;
4038 goto out;
4039 }
4040 else if (kwm == KWM_NO) {
4041 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4042 curproxy->options &= ~PR_O_HTTP_MODE;
4043 goto out;
4044 }
4045 }
4046 else if (strcmp(args[1], "http-keep-alive") == 0) {
4047 if (kwm == KWM_STD) {
4048 curproxy->options &= ~PR_O_HTTP_MODE;
4049 curproxy->options |= PR_O_HTTP_KAL;
4050 goto out;
4051 }
4052 else if (kwm == KWM_NO) {
4053 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4054 curproxy->options &= ~PR_O_HTTP_MODE;
4055 goto out;
4056 }
4057 }
4058 else if (strcmp(args[1], "http-tunnel") == 0) {
4059 if (kwm == KWM_STD) {
4060 curproxy->options &= ~PR_O_HTTP_MODE;
4061 curproxy->options |= PR_O_HTTP_TUN;
4062 goto out;
4063 }
4064 else if (kwm == KWM_NO) {
4065 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4066 curproxy->options &= ~PR_O_HTTP_MODE;
4067 goto out;
4068 }
4069 }
4070
Willy Tarreau3842f002009-06-14 11:39:52 +02004071 if (kwm != KWM_STD) {
4072 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004073 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004076 }
4077
Emeric Brun3a058f32009-06-30 18:26:00 +02004078 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004079 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004080 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004081 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004082 if (*(args[2]) != '\0') {
4083 if (!strcmp(args[2], "clf")) {
4084 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004085 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004086 } else {
4087 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[2]);
Willy Tarreau93893792009-07-23 13:19:11 +02004088 err_code |= ERR_ALERT | ERR_FATAL;
4089 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004090 }
4091 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004092 if (curproxy->conf.logformat_string != default_http_log_format &&
4093 curproxy->conf.logformat_string != default_tcp_log_format &&
4094 curproxy->conf.logformat_string != clf_http_log_format)
4095 free(curproxy->conf.logformat_string);
4096 curproxy->conf.logformat_string = logformat;
4097
4098 free(curproxy->conf.lfs_file);
4099 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4100 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004101 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004102 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004103 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004104 if (curproxy->conf.logformat_string != default_http_log_format &&
4105 curproxy->conf.logformat_string != default_tcp_log_format &&
4106 curproxy->conf.logformat_string != clf_http_log_format)
4107 free(curproxy->conf.logformat_string);
4108 curproxy->conf.logformat_string = default_tcp_log_format;
4109
4110 free(curproxy->conf.lfs_file);
4111 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4112 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004113 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004114 else if (!strcmp(args[1], "tcpka")) {
4115 /* enable TCP keep-alives on client and server sessions */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004116 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004117 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004118
4119 if (curproxy->cap & PR_CAP_FE)
4120 curproxy->options |= PR_O_TCP_CLI_KA;
4121 if (curproxy->cap & PR_CAP_BE)
4122 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004123 }
4124 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004125 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004126 err_code |= ERR_WARN;
4127
Willy Tarreaubaaee002006-06-26 02:48:02 +02004128 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004129 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004130 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004131 curproxy->options2 &= ~PR_O2_CHK_ANY;
4132 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004133 if (!*args[2]) { /* no argument */
4134 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4135 curproxy->check_len = strlen(DEF_CHECK_REQ);
4136 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004137 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004138 curproxy->check_req = (char *)malloc(reqlen);
4139 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004140 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004141 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004142 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004143 if (*args[4])
4144 reqlen += strlen(args[4]);
4145 else
4146 reqlen += strlen("HTTP/1.0");
4147
4148 curproxy->check_req = (char *)malloc(reqlen);
4149 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004150 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004151 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02004152 }
4153 else if (!strcmp(args[1], "ssl-hello-chk")) {
4154 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004155 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004156 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004157
Willy Tarreaua534fea2008-08-03 12:19:50 +02004158 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004159 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004160 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004161 curproxy->options2 |= PR_O2_SSL3_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004162 }
Willy Tarreau23677902007-05-08 23:50:35 +02004163 else if (!strcmp(args[1], "smtpchk")) {
4164 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004165 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004166 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004167 curproxy->options2 &= ~PR_O2_CHK_ANY;
4168 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004169
4170 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4171 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4172 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4173 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4174 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4175 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4176 curproxy->check_req = (char *)malloc(reqlen);
4177 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4178 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4179 } else {
4180 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4181 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4182 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4183 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4184 }
4185 }
4186 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004187 else if (!strcmp(args[1], "pgsql-check")) {
4188 /* use PostgreSQL request to check servers' health */
4189 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4190 err_code |= ERR_WARN;
4191
4192 free(curproxy->check_req);
4193 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004194 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004195 curproxy->options2 |= PR_O2_PGSQL_CHK;
4196
4197 if (*(args[2])) {
4198 int cur_arg = 2;
4199
4200 while (*(args[cur_arg])) {
4201 if (strcmp(args[cur_arg], "user") == 0) {
4202 char * packet;
4203 uint32_t packet_len;
4204 uint32_t pv;
4205
4206 /* suboption header - needs additional argument for it */
4207 if (*(args[cur_arg+1]) == 0) {
4208 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4209 file, linenum, args[0], args[1], args[cur_arg]);
4210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
4212 }
4213
4214 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4215 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4216 pv = htonl(0x30000); /* protocol version 3.0 */
4217
4218 packet = (char*) calloc(1, packet_len);
4219
4220 memcpy(packet + 4, &pv, 4);
4221
4222 /* copy "user" */
4223 memcpy(packet + 8, "user", 4);
4224
4225 /* copy username */
4226 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4227
4228 free(curproxy->check_req);
4229 curproxy->check_req = packet;
4230 curproxy->check_len = packet_len;
4231
4232 packet_len = htonl(packet_len);
4233 memcpy(packet, &packet_len, 4);
4234 cur_arg += 2;
4235 } else {
4236 /* unknown suboption - catchall */
4237 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4238 file, linenum, args[0], args[1]);
4239 err_code |= ERR_ALERT | ERR_FATAL;
4240 goto out;
4241 }
4242 } /* end while loop */
4243 }
4244 }
4245
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004246 else if (!strcmp(args[1], "redis-check")) {
4247 /* use REDIS PING request to check servers' health */
4248 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4249 err_code |= ERR_WARN;
4250
4251 free(curproxy->check_req);
4252 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004253 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004254 curproxy->options2 |= PR_O2_REDIS_CHK;
4255
4256 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4257 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4258 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
4259 }
4260
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004261 else if (!strcmp(args[1], "mysql-check")) {
4262 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4264 err_code |= ERR_WARN;
4265
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004266 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004267 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004268 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004269 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004270
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004271 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004272 * const char mysql40_client_auth_pkt[] = {
4273 * "\x0e\x00\x00" // packet length
4274 * "\x01" // packet number
4275 * "\x00\x00" // client capabilities
4276 * "\x00\x00\x01" // max packet
4277 * "haproxy\x00" // username (null terminated string)
4278 * "\x00" // filler (always 0x00)
4279 * "\x01\x00\x00" // packet length
4280 * "\x00" // packet number
4281 * "\x01" // COM_QUIT command
4282 * };
4283 */
4284
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004285 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4286 * const char mysql41_client_auth_pkt[] = {
4287 * "\x0e\x00\x00\" // packet length
4288 * "\x01" // packet number
4289 * "\x00\x00\x00\x00" // client capabilities
4290 * "\x00\x00\x00\x01" // max packet
4291 * "\x21" // character set (UTF-8)
4292 * char[23] // All zeroes
4293 * "haproxy\x00" // username (null terminated string)
4294 * "\x00" // filler (always 0x00)
4295 * "\x01\x00\x00" // packet length
4296 * "\x00" // packet number
4297 * "\x01" // COM_QUIT command
4298 * };
4299 */
4300
4301
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004302 if (*(args[2])) {
4303 int cur_arg = 2;
4304
4305 while (*(args[cur_arg])) {
4306 if (strcmp(args[cur_arg], "user") == 0) {
4307 char *mysqluser;
4308 int packetlen, reqlen, userlen;
4309
4310 /* suboption header - needs additional argument for it */
4311 if (*(args[cur_arg+1]) == 0) {
4312 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4313 file, linenum, args[0], args[1], args[cur_arg]);
4314 err_code |= ERR_ALERT | ERR_FATAL;
4315 goto out;
4316 }
4317 mysqluser = args[cur_arg + 1];
4318 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004319
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004320 if (*(args[cur_arg+2])) {
4321 if (!strcmp(args[cur_arg+2], "post-41")) {
4322 packetlen = userlen + 7 + 27;
4323 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004324
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004325 free(curproxy->check_req);
4326 curproxy->check_req = (char *)calloc(1, reqlen);
4327 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004328
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004329 snprintf(curproxy->check_req, 4, "%c%c%c",
4330 ((unsigned char) packetlen & 0xff),
4331 ((unsigned char) (packetlen >> 8) & 0xff),
4332 ((unsigned char) (packetlen >> 16) & 0xff));
4333
4334 curproxy->check_req[3] = 1;
4335 curproxy->check_req[5] = 130;
4336 curproxy->check_req[11] = 1;
4337 curproxy->check_req[12] = 33;
4338 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4339 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4340 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4341 cur_arg += 3;
4342 } else {
4343 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
4346 }
4347 } else {
4348 packetlen = userlen + 7;
4349 reqlen = packetlen + 9;
4350
4351 free(curproxy->check_req);
4352 curproxy->check_req = (char *)calloc(1, reqlen);
4353 curproxy->check_len = reqlen;
4354
4355 snprintf(curproxy->check_req, 4, "%c%c%c",
4356 ((unsigned char) packetlen & 0xff),
4357 ((unsigned char) (packetlen >> 8) & 0xff),
4358 ((unsigned char) (packetlen >> 16) & 0xff));
4359
4360 curproxy->check_req[3] = 1;
4361 curproxy->check_req[5] = 128;
4362 curproxy->check_req[8] = 1;
4363 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4364 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4365 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4366 cur_arg += 2;
4367 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004368 } else {
4369 /* unknown suboption - catchall */
4370 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4371 file, linenum, args[0], args[1]);
4372 err_code |= ERR_ALERT | ERR_FATAL;
4373 goto out;
4374 }
4375 } /* end while loop */
4376 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004377 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004378 else if (!strcmp(args[1], "ldap-check")) {
4379 /* use LDAP request to check servers' health */
4380 free(curproxy->check_req);
4381 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004382 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004383 curproxy->options2 |= PR_O2_LDAP_CHK;
4384
4385 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4386 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4387 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
4388 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004389 else if (!strcmp(args[1], "tcp-check")) {
4390 /* use raw TCPCHK send/expect to check servers' health */
4391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4392 err_code |= ERR_WARN;
4393
4394 free(curproxy->check_req);
4395 curproxy->check_req = NULL;
4396 curproxy->options2 &= ~PR_O2_CHK_ANY;
4397 curproxy->options2 |= PR_O2_TCPCHK_CHK;
4398 }
Simon Horman98637e52014-06-20 12:30:16 +09004399 else if (!strcmp(args[1], "external-check")) {
4400 /* excute an external command to check servers' health */
4401 free(curproxy->check_req);
4402 curproxy->check_req = NULL;
4403 curproxy->options2 &= ~PR_O2_CHK_ANY;
4404 curproxy->options2 |= PR_O2_EXT_CHK;
4405 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004406 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004407 int cur_arg;
4408
4409 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4410 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004411 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004412
Willy Tarreau87cf5142011-08-19 22:57:24 +02004413 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004414
4415 free(curproxy->fwdfor_hdr_name);
4416 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4417 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4418
4419 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4420 cur_arg = 2;
4421 while (*(args[cur_arg])) {
4422 if (!strcmp(args[cur_arg], "except")) {
4423 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004424 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004425 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4426 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004427 err_code |= ERR_ALERT | ERR_FATAL;
4428 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004429 }
4430 /* flush useless bits */
4431 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004432 cur_arg += 2;
4433 } else if (!strcmp(args[cur_arg], "header")) {
4434 /* suboption header - needs additional argument for it */
4435 if (*(args[cur_arg+1]) == 0) {
4436 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4437 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_ALERT | ERR_FATAL;
4439 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004440 }
4441 free(curproxy->fwdfor_hdr_name);
4442 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4443 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4444 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004445 } else if (!strcmp(args[cur_arg], "if-none")) {
4446 curproxy->options &= ~PR_O_FF_ALWAYS;
4447 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004448 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004449 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004450 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004451 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004454 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004455 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004456 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004457 else if (!strcmp(args[1], "originalto")) {
4458 int cur_arg;
4459
4460 /* insert x-original-to field, but not for the IP address listed as an except.
4461 * set default options (ie: bitfield, header name, etc)
4462 */
4463
4464 curproxy->options |= PR_O_ORGTO;
4465
4466 free(curproxy->orgto_hdr_name);
4467 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4468 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4469
Willy Tarreau87cf5142011-08-19 22:57:24 +02004470 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004471 cur_arg = 2;
4472 while (*(args[cur_arg])) {
4473 if (!strcmp(args[cur_arg], "except")) {
4474 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004475 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 +02004476 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4477 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004478 err_code |= ERR_ALERT | ERR_FATAL;
4479 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004480 }
4481 /* flush useless bits */
4482 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4483 cur_arg += 2;
4484 } else if (!strcmp(args[cur_arg], "header")) {
4485 /* suboption header - needs additional argument for it */
4486 if (*(args[cur_arg+1]) == 0) {
4487 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4488 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004489 err_code |= ERR_ALERT | ERR_FATAL;
4490 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004491 }
4492 free(curproxy->orgto_hdr_name);
4493 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4494 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4495 cur_arg += 2;
4496 } else {
4497 /* unknown suboption - catchall */
4498 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4499 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004500 err_code |= ERR_ALERT | ERR_FATAL;
4501 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004502 }
4503 } /* end while loop */
4504 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004505 else {
4506 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004507 err_code |= ERR_ALERT | ERR_FATAL;
4508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004509 }
Willy Tarreau93893792009-07-23 13:19:11 +02004510 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004511 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004512 else if (!strcmp(args[0], "default_backend")) {
4513 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004514 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004515
4516 if (*(args[1]) == 0) {
4517 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004518 err_code |= ERR_ALERT | ERR_FATAL;
4519 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004520 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004521 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004522 curproxy->defbe.name = strdup(args[1]);
4523 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004524 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004525 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004526 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004527
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004528 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4529 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 +01004530 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004531 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004532 /* enable reconnections to dispatch */
4533 curproxy->options |= PR_O_REDISP;
4534 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004535 else if (!strcmp(args[0], "http-check")) {
4536 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004537 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004538
4539 if (strcmp(args[1], "disable-on-404") == 0) {
4540 /* enable a graceful server shutdown on an HTTP 404 response */
4541 curproxy->options |= PR_O_DISABLE404;
4542 }
Willy Tarreauef781042010-01-27 11:53:01 +01004543 else if (strcmp(args[1], "send-state") == 0) {
4544 /* enable emission of the apparent state of a server in HTTP checks */
4545 curproxy->options2 |= PR_O2_CHK_SNDST;
4546 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004547 else if (strcmp(args[1], "expect") == 0) {
4548 const char *ptr_arg;
4549 int cur_arg;
4550
4551 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4552 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4553 err_code |= ERR_ALERT | ERR_FATAL;
4554 goto out;
4555 }
4556
4557 cur_arg = 2;
4558 /* consider exclamation marks, sole or at the beginning of a word */
4559 while (*(ptr_arg = args[cur_arg])) {
4560 while (*ptr_arg == '!') {
4561 curproxy->options2 ^= PR_O2_EXP_INV;
4562 ptr_arg++;
4563 }
4564 if (*ptr_arg)
4565 break;
4566 cur_arg++;
4567 }
4568 /* now ptr_arg points to the beginning of a word past any possible
4569 * exclamation mark, and cur_arg is the argument which holds this word.
4570 */
4571 if (strcmp(ptr_arg, "status") == 0) {
4572 if (!*(args[cur_arg + 1])) {
4573 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4574 file, linenum, args[0], args[1], ptr_arg);
4575 err_code |= ERR_ALERT | ERR_FATAL;
4576 goto out;
4577 }
4578 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004579 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004580 curproxy->expect_str = strdup(args[cur_arg + 1]);
4581 }
4582 else if (strcmp(ptr_arg, "string") == 0) {
4583 if (!*(args[cur_arg + 1])) {
4584 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4585 file, linenum, args[0], args[1], ptr_arg);
4586 err_code |= ERR_ALERT | ERR_FATAL;
4587 goto out;
4588 }
4589 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004590 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004591 curproxy->expect_str = strdup(args[cur_arg + 1]);
4592 }
4593 else if (strcmp(ptr_arg, "rstatus") == 0) {
4594 if (!*(args[cur_arg + 1])) {
4595 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4596 file, linenum, args[0], args[1], ptr_arg);
4597 err_code |= ERR_ALERT | ERR_FATAL;
4598 goto out;
4599 }
4600 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004601 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004602 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004603 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004604 free(curproxy->expect_regex);
4605 curproxy->expect_regex = NULL;
4606 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004607 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004608 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4609 error = NULL;
4610 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4611 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4612 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4613 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004614 err_code |= ERR_ALERT | ERR_FATAL;
4615 goto out;
4616 }
4617 }
4618 else if (strcmp(ptr_arg, "rstring") == 0) {
4619 if (!*(args[cur_arg + 1])) {
4620 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4621 file, linenum, args[0], args[1], ptr_arg);
4622 err_code |= ERR_ALERT | ERR_FATAL;
4623 goto out;
4624 }
4625 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004626 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004627 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004628 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004629 free(curproxy->expect_regex);
4630 curproxy->expect_regex = NULL;
4631 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004632 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004633 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4634 error = NULL;
4635 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4636 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4637 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4638 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004639 err_code |= ERR_ALERT | ERR_FATAL;
4640 goto out;
4641 }
4642 }
4643 else {
4644 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4645 file, linenum, args[0], args[1], ptr_arg);
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
4649 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004650 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004651 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 +02004652 err_code |= ERR_ALERT | ERR_FATAL;
4653 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004654 }
4655 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004656 else if (!strcmp(args[0], "tcp-check")) {
4657 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4658 err_code |= ERR_WARN;
4659
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004660 if (strcmp(args[1], "connect") == 0) {
4661 const char *ptr_arg;
4662 int cur_arg;
4663 struct tcpcheck_rule *tcpcheck;
4664 struct list *l;
4665
4666 /* check if first rule is also a 'connect' action */
4667 l = (struct list *)&curproxy->tcpcheck_rules;
4668 if (l->p != l->n) {
4669 tcpcheck = (struct tcpcheck_rule *)l->n;
4670 if (tcpcheck && tcpcheck->action != TCPCHK_ACT_CONNECT) {
4671 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
4672 file, linenum);
4673 err_code |= ERR_ALERT | ERR_FATAL;
4674 goto out;
4675 }
4676 }
4677
4678 cur_arg = 2;
4679 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4680 tcpcheck->action = TCPCHK_ACT_CONNECT;
4681
4682 /* parsing each parameters to fill up the rule */
4683 while (*(ptr_arg = args[cur_arg])) {
4684 /* tcp port */
4685 if (strcmp(args[cur_arg], "port") == 0) {
4686 if ( (atol(args[cur_arg + 1]) > 65535) ||
4687 (atol(args[cur_arg + 1]) < 1) ){
4688 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
4689 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
4690 err_code |= ERR_ALERT | ERR_FATAL;
4691 goto out;
4692 }
4693 tcpcheck->port = atol(args[cur_arg + 1]);
4694 cur_arg += 2;
4695 }
4696 /* send proxy protocol */
4697 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
4698 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
4699 cur_arg++;
4700 }
4701#ifdef USE_OPENSSL
4702 else if (strcmp(args[cur_arg], "ssl") == 0) {
4703 curproxy->options |= PR_O_TCPCHK_SSL;
4704 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
4705 cur_arg++;
4706 }
4707#endif /* USE_OPENSSL */
4708 else {
4709#ifdef USE_OPENSSL
4710 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
4711#else /* USE_OPENSSL */
4712 Alert("parsing [%s:%d] : '%s %s' expects 'port', 'send-proxy' or but got '%s' as argument.\n",
4713#endif /* USE_OPENSSL */
4714 file, linenum, args[0], args[1], args[cur_arg]);
4715 err_code |= ERR_ALERT | ERR_FATAL;
4716 goto out;
4717 }
4718
4719 }
4720
4721 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4722 }
4723 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004724 if (! *(args[2]) ) {
4725 /* SEND string expected */
4726 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
4727 file, linenum, args[0], args[1], args[2]);
4728 err_code |= ERR_ALERT | ERR_FATAL;
4729 goto out;
4730 } else {
4731 struct tcpcheck_rule *tcpcheck;
4732
4733 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4734
4735 tcpcheck->action = TCPCHK_ACT_SEND;
4736 tcpcheck->string_len = strlen(args[2]);
4737 tcpcheck->string = strdup(args[2]);
4738 tcpcheck->expect_regex = NULL;
4739
4740 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4741 }
4742 }
4743 else if (strcmp(args[1], "send-binary") == 0) {
4744 if (! *(args[2]) ) {
4745 /* SEND binary string expected */
4746 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
4747 file, linenum, args[0], args[1], args[2]);
4748 err_code |= ERR_ALERT | ERR_FATAL;
4749 goto out;
4750 } else {
4751 struct tcpcheck_rule *tcpcheck;
4752 char *err = NULL;
4753
4754 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4755
4756 tcpcheck->action = TCPCHK_ACT_SEND;
4757 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4758 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4759 file, linenum, args[0], args[1], args[2], err);
4760 err_code |= ERR_ALERT | ERR_FATAL;
4761 goto out;
4762 }
4763 tcpcheck->expect_regex = NULL;
4764
4765 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4766 }
4767 }
4768 else if (strcmp(args[1], "expect") == 0) {
4769 const char *ptr_arg;
4770 int cur_arg;
4771 int inverse = 0;
4772
4773 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4774 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4775 err_code |= ERR_ALERT | ERR_FATAL;
4776 goto out;
4777 }
4778
4779 cur_arg = 2;
4780 /* consider exclamation marks, sole or at the beginning of a word */
4781 while (*(ptr_arg = args[cur_arg])) {
4782 while (*ptr_arg == '!') {
4783 inverse = !inverse;
4784 ptr_arg++;
4785 }
4786 if (*ptr_arg)
4787 break;
4788 cur_arg++;
4789 }
4790 /* now ptr_arg points to the beginning of a word past any possible
4791 * exclamation mark, and cur_arg is the argument which holds this word.
4792 */
4793 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004794 struct tcpcheck_rule *tcpcheck;
4795 char *err = NULL;
4796
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004797 if (!*(args[cur_arg + 1])) {
4798 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
4799 file, linenum, args[0], args[1], ptr_arg);
4800 err_code |= ERR_ALERT | ERR_FATAL;
4801 goto out;
4802 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004803
4804 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4805
4806 tcpcheck->action = TCPCHK_ACT_EXPECT;
4807 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
4808 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
4809 file, linenum, args[0], args[1], args[2], err);
4810 err_code |= ERR_ALERT | ERR_FATAL;
4811 goto out;
4812 }
4813 tcpcheck->expect_regex = NULL;
4814 tcpcheck->inverse = inverse;
4815
4816 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4817 }
4818 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004819 struct tcpcheck_rule *tcpcheck;
4820
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004821 if (!*(args[cur_arg + 1])) {
4822 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4823 file, linenum, args[0], args[1], ptr_arg);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004827
4828 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4829
4830 tcpcheck->action = TCPCHK_ACT_EXPECT;
4831 tcpcheck->string_len = strlen(args[cur_arg + 1]);
4832 tcpcheck->string = strdup(args[cur_arg + 1]);
4833 tcpcheck->expect_regex = NULL;
4834 tcpcheck->inverse = inverse;
4835
4836 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4837 }
4838 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01004839 struct tcpcheck_rule *tcpcheck;
4840
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004841 if (!*(args[cur_arg + 1])) {
4842 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4843 file, linenum, args[0], args[1], ptr_arg);
4844 err_code |= ERR_ALERT | ERR_FATAL;
4845 goto out;
4846 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004847
4848 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
4849
4850 tcpcheck->action = TCPCHK_ACT_EXPECT;
4851 tcpcheck->string_len = 0;
4852 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004853 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
4854 error = NULL;
4855 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
4856 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4857 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4858 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004859 err_code |= ERR_ALERT | ERR_FATAL;
4860 goto out;
4861 }
4862 tcpcheck->inverse = inverse;
4863
4864 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
4865 }
4866 else {
4867 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
4868 file, linenum, args[0], args[1], ptr_arg);
4869 err_code |= ERR_ALERT | ERR_FATAL;
4870 goto out;
4871 }
4872 }
4873 else {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01004874 Alert("parsing [%s:%d] : '%s' only supports 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004875 err_code |= ERR_ALERT | ERR_FATAL;
4876 goto out;
4877 }
4878 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01004879 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02004880 if (curproxy == &defproxy) {
4881 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004882 err_code |= ERR_ALERT | ERR_FATAL;
4883 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02004884 }
4885
Willy Tarreaub80c2302007-11-30 20:51:32 +01004886 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004887 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004888
4889 if (strcmp(args[1], "fail") == 0) {
4890 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01004891 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01004892 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4893 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004896 }
4897
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004898 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4899 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
4900 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02004901 err_code |= ERR_ALERT | ERR_FATAL;
4902 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004903 }
4904 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
4905 }
4906 else {
4907 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004908 err_code |= ERR_ALERT | ERR_FATAL;
4909 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01004910 }
4911 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004912#ifdef TPROXY
4913 else if (!strcmp(args[0], "transparent")) {
4914 /* enable transparent proxy connections */
4915 curproxy->options |= PR_O_TRANSP;
4916 }
4917#endif
4918 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004919 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004920 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004921
Willy Tarreaubaaee002006-06-26 02:48:02 +02004922 if (*(args[1]) == 0) {
4923 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004926 }
4927 curproxy->maxconn = atol(args[1]);
4928 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004929 else if (!strcmp(args[0], "backlog")) { /* backlog */
4930 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004931 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004932
4933 if (*(args[1]) == 0) {
4934 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004935 err_code |= ERR_ALERT | ERR_FATAL;
4936 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01004937 }
4938 curproxy->backlog = atol(args[1]);
4939 }
Willy Tarreau86034312006-12-29 00:10:33 +01004940 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01004941 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02004942 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004943
Willy Tarreau86034312006-12-29 00:10:33 +01004944 if (*(args[1]) == 0) {
4945 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004946 err_code |= ERR_ALERT | ERR_FATAL;
4947 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01004948 }
4949 curproxy->fullconn = atol(args[1]);
4950 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004951 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
4952 if (*(args[1]) == 0) {
4953 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004954 err_code |= ERR_ALERT | ERR_FATAL;
4955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004956 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004957 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
4958 if (err) {
4959 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
4960 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004961 err_code |= ERR_ALERT | ERR_FATAL;
4962 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004963 }
4964 curproxy->grace = val;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004965 }
4966 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01004967 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004968 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004969 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004970
Willy Tarreaubaaee002006-06-26 02:48:02 +02004971 if (curproxy == &defproxy) {
4972 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004973 err_code |= ERR_ALERT | ERR_FATAL;
4974 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004975 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01004976 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004977 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004978
Willy Tarreau902636f2013-03-10 19:44:48 +01004979 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004980 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01004981 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004982 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004983 goto out;
4984 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01004985
4986 proto = protocol_by_family(sk->ss_family);
4987 if (!proto || !proto->connect) {
4988 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
4989 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01004990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
4992 }
4993
4994 if (port1 != port2) {
4995 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
4996 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004999 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005000
5001 if (!port1) {
5002 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5003 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
5006 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005007
Willy Tarreaud5191e72010-02-09 20:50:45 +01005008 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005009 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005010 }
5011 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005012 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005013 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005014
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005015 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5016 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005020 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005021 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005022 /**
5023 * The syntax for hash-type config element is
5024 * hash-type {map-based|consistent} [[<algo>] avalanche]
5025 *
5026 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5027 */
5028 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005029
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005030 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5031 err_code |= ERR_WARN;
5032
5033 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005034 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5035 }
5036 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005037 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5038 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005039 else if (strcmp(args[1], "avalanche") == 0) {
5040 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]);
5041 err_code |= ERR_ALERT | ERR_FATAL;
5042 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005043 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005044 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005045 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
5048 }
Bhaskar98634f02013-10-29 23:30:51 -04005049
5050 /* set the hash function to use */
5051 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005052 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005053 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005054
5055 /* if consistent with no argument, then avalanche modifier is also applied */
5056 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5057 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005058 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005059 /* set the hash function */
5060 if (!strcmp(args[2], "sdbm")) {
5061 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5062 }
5063 else if (!strcmp(args[2], "djb2")) {
5064 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005065 }
5066 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005067 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005068 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005069 else if (!strcmp(args[2], "crc32")) {
5070 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5071 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005072 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005073 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 -05005074 err_code |= ERR_ALERT | ERR_FATAL;
5075 goto out;
5076 }
5077
5078 /* set the hash modifier */
5079 if (!strcmp(args[3], "avalanche")) {
5080 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5081 }
5082 else if (*args[3]) {
5083 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5084 err_code |= ERR_ALERT | ERR_FATAL;
5085 goto out;
5086 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005087 }
William Lallemanda73203e2012-03-12 12:48:57 +01005088 }
William Lallemanda73203e2012-03-12 12:48:57 +01005089 else if (strcmp(args[0], "unique-id-format") == 0) {
5090 if (!*(args[1])) {
5091 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5092 err_code |= ERR_ALERT | ERR_FATAL;
5093 goto out;
5094 }
William Lallemand3203ff42012-11-11 17:30:56 +01005095 if (*(args[2])) {
5096 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5097 err_code |= ERR_ALERT | ERR_FATAL;
5098 goto out;
5099 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005100 free(curproxy->conf.uniqueid_format_string);
5101 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005102
Willy Tarreau62a61232013-04-12 18:13:46 +02005103 free(curproxy->conf.uif_file);
5104 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5105 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005106 }
William Lallemanda73203e2012-03-12 12:48:57 +01005107
5108 else if (strcmp(args[0], "unique-id-header") == 0) {
5109 if (!*(args[1])) {
5110 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5111 err_code |= ERR_ALERT | ERR_FATAL;
5112 goto out;
5113 }
5114 free(curproxy->header_unique_id);
5115 curproxy->header_unique_id = strdup(args[1]);
5116 }
5117
William Lallemand723b73a2012-02-08 16:37:49 +01005118 else if (strcmp(args[0], "log-format") == 0) {
5119 if (!*(args[1])) {
5120 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5121 err_code |= ERR_ALERT | ERR_FATAL;
5122 goto out;
5123 }
William Lallemand3203ff42012-11-11 17:30:56 +01005124 if (*(args[2])) {
5125 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5126 err_code |= ERR_ALERT | ERR_FATAL;
5127 goto out;
5128 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005129
Willy Tarreau62a61232013-04-12 18:13:46 +02005130 if (curproxy->conf.logformat_string != default_http_log_format &&
5131 curproxy->conf.logformat_string != default_tcp_log_format &&
5132 curproxy->conf.logformat_string != clf_http_log_format)
5133 free(curproxy->conf.logformat_string);
5134 curproxy->conf.logformat_string = strdup(args[1]);
5135
5136 free(curproxy->conf.lfs_file);
5137 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5138 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005139
5140 /* get a chance to improve log-format error reporting by
5141 * reporting the correct line-number when possible.
5142 */
5143 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5144 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5145 file, linenum, curproxy->id);
5146 err_code |= ERR_WARN;
5147 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005148 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005149 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5150 if (*(args[1]) == 0) {
5151 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
5155 free(curproxy->log_tag);
5156 curproxy->log_tag = strdup(args[1]);
5157 }
William Lallemand0f99e342011-10-12 17:50:54 +02005158 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5159 /* delete previous herited or defined syslog servers */
5160 struct logsrv *back;
5161
5162 if (*(args[1]) != 0) {
5163 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
5166 }
5167
William Lallemand723b73a2012-02-08 16:37:49 +01005168 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5169 LIST_DEL(&tmplogsrv->list);
5170 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005171 }
5172 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005173 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005174 struct logsrv *logsrv;
5175
Willy Tarreaubaaee002006-06-26 02:48:02 +02005176 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005177 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005178 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005179 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005180 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005181 LIST_INIT(&node->list);
5182 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5183 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005184 }
5185 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005186 struct sockaddr_storage *sk;
5187 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005188 int arg = 0;
5189 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005190
5191 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005192
Willy Tarreau18324f52014-06-27 18:10:07 +02005193 /* just after the address, a length may be specified */
5194 if (strcmp(args[arg+2], "len") == 0) {
5195 len = atoi(args[arg+3]);
5196 if (len < 80 || len > 65535) {
5197 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5198 file, linenum, args[arg+3]);
5199 err_code |= ERR_ALERT | ERR_FATAL;
5200 goto out;
5201 }
5202 logsrv->maxlen = len;
5203
5204 /* skip these two args */
5205 arg += 2;
5206 }
5207 else
5208 logsrv->maxlen = MAX_SYSLOG_LEN;
5209
5210 if (logsrv->maxlen > global.max_syslog_len) {
5211 global.max_syslog_len = logsrv->maxlen;
5212 logline = realloc(logline, global.max_syslog_len + 1);
5213 }
5214
5215 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005216 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005217 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220
Willy Tarreaubaaee002006-06-26 02:48:02 +02005221 }
5222
William Lallemand0f99e342011-10-12 17:50:54 +02005223 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005224 if (*(args[arg+3])) {
5225 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005226 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005227 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005228 err_code |= ERR_ALERT | ERR_FATAL;
5229 goto out;
5230
Willy Tarreaubaaee002006-06-26 02:48:02 +02005231 }
5232 }
5233
William Lallemand0f99e342011-10-12 17:50:54 +02005234 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005235 if (*(args[arg+4])) {
5236 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005237 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005238 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005239 err_code |= ERR_ALERT | ERR_FATAL;
5240 goto out;
5241
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005242 }
5243 }
5244
Willy Tarreau902636f2013-03-10 19:44:48 +01005245 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005246 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005247 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005248 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005249 goto out;
5250 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005251
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005252 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005253
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005254 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005255 if (port1 != port2) {
5256 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5257 file, linenum, args[0], args[1]);
5258 err_code |= ERR_ALERT | ERR_FATAL;
5259 goto out;
5260 }
5261
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005262 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005263 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005264 }
William Lallemand0f99e342011-10-12 17:50:54 +02005265
5266 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005267 }
5268 else {
5269 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5270 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005271 err_code |= ERR_ALERT | ERR_FATAL;
5272 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005273 }
5274 }
5275 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005276 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005277 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005278 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005279 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005280
Willy Tarreau977b8e42006-12-29 14:19:17 +01005281 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005282 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005283
Willy Tarreaubaaee002006-06-26 02:48:02 +02005284 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005285 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5286 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005289 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005290
5291 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005292 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5293 free(curproxy->conn_src.iface_name);
5294 curproxy->conn_src.iface_name = NULL;
5295 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005296
Willy Tarreau902636f2013-03-10 19:44:48 +01005297 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005298 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005299 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005300 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005301 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005302 goto out;
5303 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005304
5305 proto = protocol_by_family(sk->ss_family);
5306 if (!proto || !proto->connect) {
5307 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005308 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005312
5313 if (port1 != port2) {
5314 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5315 file, linenum, args[0], args[1]);
5316 err_code |= ERR_ALERT | ERR_FATAL;
5317 goto out;
5318 }
5319
Willy Tarreauef9a3602012-12-08 22:29:20 +01005320 curproxy->conn_src.source_addr = *sk;
5321 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005322
5323 cur_arg = 2;
5324 while (*(args[cur_arg])) {
5325 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005326#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5327#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005328 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005329 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5330 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005331 err_code |= ERR_ALERT | ERR_FATAL;
5332 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005333 }
5334#endif
5335 if (!*args[cur_arg + 1]) {
5336 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5337 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005340 }
5341
5342 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005343 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5344 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005345 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005346 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5347 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005348 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5349 char *name, *end;
5350
5351 name = args[cur_arg+1] + 7;
5352 while (isspace(*name))
5353 name++;
5354
5355 end = name;
5356 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5357 end++;
5358
Willy Tarreauef9a3602012-12-08 22:29:20 +01005359 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5360 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5361 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5362 curproxy->conn_src.bind_hdr_len = end - name;
5363 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5364 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5365 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005366
5367 /* now look for an occurrence number */
5368 while (isspace(*end))
5369 end++;
5370 if (*end == ',') {
5371 end++;
5372 name = end;
5373 if (*end == '-')
5374 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005375 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005376 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005377 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005378 }
5379
Willy Tarreauef9a3602012-12-08 22:29:20 +01005380 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005381 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5382 " occurrences values smaller than %d.\n",
5383 file, linenum, MAX_HDR_HISTORY);
5384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
5386 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005387 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005388 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005389
Willy Tarreau902636f2013-03-10 19:44:48 +01005390 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005391 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005392 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005393 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005394 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005395 goto out;
5396 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005397
5398 proto = protocol_by_family(sk->ss_family);
5399 if (!proto || !proto->connect) {
5400 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5401 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005402 err_code |= ERR_ALERT | ERR_FATAL;
5403 goto out;
5404 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005405
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005406 if (port1 != port2) {
5407 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5408 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005409 err_code |= ERR_ALERT | ERR_FATAL;
5410 goto out;
5411 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005412 curproxy->conn_src.tproxy_addr = *sk;
5413 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005414 }
5415 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005416#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005417 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005418#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005419#else /* no TPROXY support */
5420 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005421 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005422 err_code |= ERR_ALERT | ERR_FATAL;
5423 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005424#endif
5425 cur_arg += 2;
5426 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005427 }
5428
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005429 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5430#ifdef SO_BINDTODEVICE
5431 if (!*args[cur_arg + 1]) {
5432 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5433 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005436 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005437 free(curproxy->conn_src.iface_name);
5438 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5439 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005440 global.last_checks |= LSTCHK_NETADM;
5441#else
5442 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5443 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005446#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005447 cur_arg += 2;
5448 continue;
5449 }
5450 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005451 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005452 err_code |= ERR_ALERT | ERR_FATAL;
5453 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005455 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005456 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5457 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5458 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005459 err_code |= ERR_ALERT | ERR_FATAL;
5460 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005461 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005462 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005463 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005464 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5465 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005466 err_code |= ERR_ALERT | ERR_FATAL;
5467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005468 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005469
5470 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005471 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005472 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005473 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005475 }
5476 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005477 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005478 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005479 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005480 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005482 }
5483 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005484 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005485 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005486 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005487 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005489 }
5490 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005491 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005492 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005493 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005494 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005495 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005496 }
5497 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005498 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005499 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005500 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005501 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005502 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005503 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005504 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005505 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005506 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005507 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005508 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005509 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005510 }
Willy Tarreaua496b602006-12-17 23:15:24 +01005511 else if (!strcmp(args[0], "reqsetbe")) { /* switch the backend from a regex, respecting case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005512 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005513 SMP_OPT_DIR_REQ, ACT_SETBE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005514 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005515 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005516 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005517
5518 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5519 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 +01005520 }
5521 else if (!strcmp(args[0], "reqisetbe")) { /* switch the backend from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005522 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005523 SMP_OPT_DIR_REQ, ACT_SETBE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005524 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005525 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005526 goto out;
Willy Tarreau40bac832014-04-28 22:37:06 +02005527
5528 if (!already_warned(WARN_REQSETBE_DEPRECATED))
5529 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 +01005530 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005531 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005532 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005533 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5534 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005535 err_code |= ERR_ALERT | ERR_FATAL;
5536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005538
5539 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005540 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005541 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005542 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 }
5545 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005546 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005547 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005548 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005549 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005551 }
5552 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005553 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005554 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005555 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005556 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 }
5559 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005560 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005561 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005562 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005563 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005565 }
5566 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005567 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005568 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005569 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005570 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005572 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005573 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005574 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005575 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005576 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005577 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005578 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005580 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005581 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005582
Willy Tarreaubaaee002006-06-26 02:48:02 +02005583 if (curproxy == &defproxy) {
5584 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005585 err_code |= ERR_ALERT | ERR_FATAL;
5586 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005587 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005588 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005589 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005590
Willy Tarreaubaaee002006-06-26 02:48:02 +02005591 if (*(args[1]) == 0) {
5592 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005593 err_code |= ERR_ALERT | ERR_FATAL;
5594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005595 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005596
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005597 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005598 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5599 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5600 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005601 err_code |= ERR_ALERT | ERR_FATAL;
5602 goto out;
5603 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005604 err_code |= warnif_cond_conflicts(cond,
5605 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
5606 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005607 }
5608 else if (*args[2]) {
5609 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5610 file, linenum, args[0], args[2]);
5611 err_code |= ERR_ALERT | ERR_FATAL;
5612 goto out;
5613 }
5614
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005615 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01005616 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005617 wl->s = strdup(args[1]);
5618 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02005619 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005620 }
5621 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005622 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005623 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5624 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005627 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005628
Willy Tarreauade5ec42010-01-28 19:33:49 +01005629 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005630 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005631 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005632 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
5635 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005636 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005637 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005638 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005639 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005640 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
5642 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005643 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005644 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005645 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005646 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005647 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 }
5649 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005650 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005651 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5652 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005653 err_code |= ERR_ALERT | ERR_FATAL;
5654 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005655 }
5656
Willy Tarreauade5ec42010-01-28 19:33:49 +01005657 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005658 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005659 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005660 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005661 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005662 }
5663 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005664 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005665 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005666 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005667 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005668 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005669 }
5670 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005671 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005672 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005673 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005674 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005675 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005676 }
5677 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01005678 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005679
Willy Tarreaubaaee002006-06-26 02:48:02 +02005680 if (curproxy == &defproxy) {
5681 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005682 err_code |= ERR_ALERT | ERR_FATAL;
5683 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005684 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005685 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005686 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687
Willy Tarreaubaaee002006-06-26 02:48:02 +02005688 if (*(args[1]) == 0) {
5689 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005690 err_code |= ERR_ALERT | ERR_FATAL;
5691 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005692 }
5693
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005694 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005695 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
5696 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
5697 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01005701 err_code |= warnif_cond_conflicts(cond,
5702 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
5703 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005704 }
5705 else if (*args[2]) {
5706 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
5707 file, linenum, args[0], args[2]);
5708 err_code |= ERR_ALERT | ERR_FATAL;
5709 goto out;
5710 }
5711
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005712 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01005713 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01005714 wl->s = strdup(args[1]);
5715 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005716 }
5717 else if (!strcmp(args[0], "errorloc") ||
5718 !strcmp(args[0], "errorloc302") ||
5719 !strcmp(args[0], "errorloc303")) { /* error location */
5720 int errnum, errlen;
5721 char *err;
5722
Willy Tarreau977b8e42006-12-29 14:19:17 +01005723 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005724 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005725
Willy Tarreaubaaee002006-06-26 02:48:02 +02005726 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005727 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005728 err_code |= ERR_ALERT | ERR_FATAL;
5729 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005730 }
5731
5732 errnum = atol(args[1]);
5733 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005734 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
5735 err = malloc(errlen);
5736 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005737 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02005738 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
5739 err = malloc(errlen);
5740 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005741 }
5742
Willy Tarreau0f772532006-12-23 20:51:41 +01005743 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5744 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005745 chunk_destroy(&curproxy->errmsg[rc]);
5746 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01005747 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 }
Willy Tarreau0f772532006-12-23 20:51:41 +01005750
5751 if (rc >= HTTP_ERR_SIZE) {
5752 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
5753 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005754 free(err);
5755 }
5756 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02005757 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
5758 int errnum, errlen, fd;
5759 char *err;
5760 struct stat stat;
5761
5762 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005763 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005764
5765 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02005766 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005769 }
5770
5771 fd = open(args[2], O_RDONLY);
5772 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
5773 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
5774 file, linenum, args[2], args[1]);
5775 if (fd >= 0)
5776 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02005777 err_code |= ERR_ALERT | ERR_FATAL;
5778 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005779 }
5780
Willy Tarreau27a674e2009-08-17 07:23:33 +02005781 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02005782 errlen = stat.st_size;
5783 } else {
5784 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02005785 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02005786 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02005787 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005788 }
5789
5790 err = malloc(errlen); /* malloc() must succeed during parsing */
5791 errnum = read(fd, err, errlen);
5792 if (errnum != errlen) {
5793 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
5794 file, linenum, args[2], args[1]);
5795 close(fd);
5796 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02005797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005799 }
5800 close(fd);
5801
5802 errnum = atol(args[1]);
5803 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
5804 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02005805 chunk_destroy(&curproxy->errmsg[rc]);
5806 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02005807 break;
5808 }
5809 }
5810
5811 if (rc >= HTTP_ERR_SIZE) {
5812 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
5813 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02005814 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02005815 free(err);
5816 }
5817 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005818 else if (!strcmp(args[0], "compression")) {
5819 struct comp *comp;
5820 if (curproxy->comp == NULL) {
5821 comp = calloc(1, sizeof(struct comp));
5822 curproxy->comp = comp;
5823 } else {
5824 comp = curproxy->comp;
5825 }
5826
5827 if (!strcmp(args[1], "algo")) {
5828 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01005829 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01005830
William Lallemand82fe75c2012-10-23 10:25:10 +02005831 cur_arg = 2;
5832 if (!*args[cur_arg]) {
5833 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
5834 file, linenum, args[0]);
5835 err_code |= ERR_ALERT | ERR_FATAL;
5836 goto out;
5837 }
5838 while (*(args[cur_arg])) {
5839 if (comp_append_algo(comp, args[cur_arg]) < 0) {
5840 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
5841 file, linenum, args[0], args[cur_arg]);
5842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
5844 }
William Lallemand552df672012-11-07 13:21:47 +01005845 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
5846 curproxy->comp->algos->end(&ctx);
5847 } else {
5848 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
5849 file, linenum, args[0], args[cur_arg]);
5850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
5852 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005853 cur_arg ++;
5854 continue;
5855 }
5856 }
Willy Tarreau70737d12012-10-27 00:34:28 +02005857 else if (!strcmp(args[1], "offload")) {
5858 comp->offload = 1;
5859 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005860 else if (!strcmp(args[1], "type")) {
5861 int cur_arg;
5862 cur_arg = 2;
5863 if (!*args[cur_arg]) {
5864 Alert("parsing [%s:%d] : '%s' expects <type>\n",
5865 file, linenum, args[0]);
5866 err_code |= ERR_ALERT | ERR_FATAL;
5867 goto out;
5868 }
5869 while (*(args[cur_arg])) {
5870 comp_append_type(comp, args[cur_arg]);
5871 cur_arg ++;
5872 continue;
5873 }
5874 }
5875 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02005876 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02005877 file, linenum, args[0]);
5878 err_code |= ERR_ALERT | ERR_FATAL;
5879 goto out;
5880 }
5881 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005882 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005883 struct cfg_kw_list *kwl;
5884 int index;
5885
5886 list_for_each_entry(kwl, &cfg_keywords.list, list) {
5887 for (index = 0; kwl->kw[index].kw != NULL; index++) {
5888 if (kwl->kw[index].section != CFG_LISTEN)
5889 continue;
5890 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
5891 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02005892 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02005893 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005894 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005895 err_code |= ERR_ALERT | ERR_FATAL;
5896 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005897 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02005898 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02005899 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005900 err_code |= ERR_WARN;
5901 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02005902 }
Willy Tarreau93893792009-07-23 13:19:11 +02005903 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02005904 }
5905 }
5906 }
William Lallemand82fe75c2012-10-23 10:25:10 +02005907
Willy Tarreau6daf3432008-01-22 16:44:08 +01005908 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02005909 err_code |= ERR_ALERT | ERR_FATAL;
5910 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005911 }
Willy Tarreau93893792009-07-23 13:19:11 +02005912 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02005913 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005914 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915}
5916
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005917int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01005918cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
5919{
5920#ifdef CONFIG_HAP_NS
5921 const char *err;
5922 const char *item = args[0];
5923
5924 if (!strcmp(item, "namespace_list")) {
5925 return 0;
5926 }
5927 else if (!strcmp(item, "namespace")) {
5928 size_t idx = 1;
5929 const char *current;
5930 while (*(current = args[idx++])) {
5931 err = invalid_char(current);
5932 if (err) {
5933 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5934 file, linenum, *err, item, current);
5935 return ERR_ALERT | ERR_FATAL;
5936 }
5937
5938 if (netns_store_lookup(current, strlen(current))) {
5939 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
5940 file, linenum, current);
5941 return ERR_ALERT | ERR_FATAL;
5942 }
5943 if (!netns_store_insert(current)) {
5944 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
5945 file, linenum, current);
5946 return ERR_ALERT | ERR_FATAL;
5947 }
5948 }
5949 }
5950
5951 return 0;
5952#else
5953 Alert("parsing [%s:%d]: namespace support is not compiled in.",
5954 file, linenum);
5955 return ERR_ALERT | ERR_FATAL;
5956#endif
5957}
5958
5959int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005960cfg_parse_users(const char *file, int linenum, char **args, int kwm)
5961{
5962
5963 int err_code = 0;
5964 const char *err;
5965
5966 if (!strcmp(args[0], "userlist")) { /* new userlist */
5967 struct userlist *newul;
5968
5969 if (!*args[1]) {
5970 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
5971 file, linenum, args[0]);
5972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
5974 }
5975
5976 err = invalid_char(args[1]);
5977 if (err) {
5978 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
5979 file, linenum, *err, args[0], args[1]);
5980 err_code |= ERR_ALERT | ERR_FATAL;
5981 goto out;
5982 }
5983
5984 for (newul = userlist; newul; newul = newul->next)
5985 if (!strcmp(newul->name, args[1])) {
5986 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
5987 file, linenum, args[1]);
5988 err_code |= ERR_WARN;
5989 goto out;
5990 }
5991
5992 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
5993 if (!newul) {
5994 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
5995 err_code |= ERR_ALERT | ERR_ABORT;
5996 goto out;
5997 }
5998
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01005999 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006000 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006001 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6002 err_code |= ERR_ALERT | ERR_ABORT;
6003 goto out;
6004 }
6005
6006 newul->next = userlist;
6007 userlist = newul;
6008
6009 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006010 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006011 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006012 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006013
6014 if (!*args[1]) {
6015 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6016 file, linenum, args[0]);
6017 err_code |= ERR_ALERT | ERR_FATAL;
6018 goto out;
6019 }
6020
6021 err = invalid_char(args[1]);
6022 if (err) {
6023 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6024 file, linenum, *err, args[0], args[1]);
6025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
6027 }
6028
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006029 for (ag = userlist->groups; ag; ag = ag->next)
6030 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006031 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6032 file, linenum, args[1], userlist->name);
6033 err_code |= ERR_ALERT;
6034 goto out;
6035 }
6036
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006037 ag = calloc(1, sizeof(*ag));
6038 if (!ag) {
6039 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6040 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006041 goto out;
6042 }
6043
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006044 ag->name = strdup(args[1]);
6045 if (!ag) {
6046 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6047 err_code |= ERR_ALERT | ERR_ABORT;
6048 goto out;
6049 }
6050
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006051 cur_arg = 2;
6052
6053 while (*args[cur_arg]) {
6054 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006055 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006056 cur_arg += 2;
6057 continue;
6058 } else {
6059 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6060 file, linenum, args[0]);
6061 err_code |= ERR_ALERT | ERR_FATAL;
6062 goto out;
6063 }
6064 }
6065
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006066 ag->next = userlist->groups;
6067 userlist->groups = ag;
6068
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006069 } else if (!strcmp(args[0], "user")) { /* new user */
6070 struct auth_users *newuser;
6071 int cur_arg;
6072
6073 if (!*args[1]) {
6074 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6075 file, linenum, args[0]);
6076 err_code |= ERR_ALERT | ERR_FATAL;
6077 goto out;
6078 }
6079
6080 for (newuser = userlist->users; newuser; newuser = newuser->next)
6081 if (!strcmp(newuser->user, args[1])) {
6082 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6083 file, linenum, args[1], userlist->name);
6084 err_code |= ERR_ALERT;
6085 goto out;
6086 }
6087
6088 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6089 if (!newuser) {
6090 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6091 err_code |= ERR_ALERT | ERR_ABORT;
6092 goto out;
6093 }
6094
6095 newuser->user = strdup(args[1]);
6096
6097 newuser->next = userlist->users;
6098 userlist->users = newuser;
6099
6100 cur_arg = 2;
6101
6102 while (*args[cur_arg]) {
6103 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006104#ifdef CONFIG_HAP_CRYPT
6105 if (!crypt("", args[cur_arg + 1])) {
6106 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6107 file, linenum, newuser->user);
6108 err_code |= ERR_ALERT | ERR_FATAL;
6109 goto out;
6110 }
6111#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006112 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6113 file, linenum);
6114 err_code |= ERR_ALERT;
6115#endif
6116 newuser->pass = strdup(args[cur_arg + 1]);
6117 cur_arg += 2;
6118 continue;
6119 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6120 newuser->pass = strdup(args[cur_arg + 1]);
6121 newuser->flags |= AU_O_INSECURE;
6122 cur_arg += 2;
6123 continue;
6124 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006125 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006126 cur_arg += 2;
6127 continue;
6128 } else {
6129 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6130 file, linenum, args[0]);
6131 err_code |= ERR_ALERT | ERR_FATAL;
6132 goto out;
6133 }
6134 }
6135 } else {
6136 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6137 err_code |= ERR_ALERT | ERR_FATAL;
6138 }
6139
6140out:
6141 return err_code;
6142}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006143
6144/*
6145 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006146 * Returns the error code, 0 if OK, or any combination of :
6147 * - ERR_ABORT: must abort ASAP
6148 * - ERR_FATAL: we can continue parsing but not start the service
6149 * - ERR_WARN: a warning has been emitted
6150 * - ERR_ALERT: an alert has been emitted
6151 * Only the two first ones can stop processing, the two others are just
6152 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006154int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006155{
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006156 char thisline[LINESIZE];
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 FILE *f;
6158 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006159 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006160 struct cfg_section *cs = NULL;
6161 struct cfg_section *ics;
6162
6163 /* Register internal sections */
6164 if (!cfg_register_section("listen", cfg_parse_listen) ||
6165 !cfg_register_section("frontend", cfg_parse_listen) ||
6166 !cfg_register_section("backend", cfg_parse_listen) ||
6167 !cfg_register_section("ruleset", cfg_parse_listen) ||
6168 !cfg_register_section("defaults", cfg_parse_listen) ||
6169 !cfg_register_section("global", cfg_parse_global) ||
6170 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006171 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006172 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006173 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006174 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006175
Willy Tarreaubaaee002006-06-26 02:48:02 +02006176 if ((f=fopen(file,"r")) == NULL)
6177 return -1;
6178
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006179 while (fgets(thisline, sizeof(thisline), f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006180 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006181 char *end;
6182 char *args[MAX_LINE_ARGS + 1];
6183 char *line = thisline;
6184
Willy Tarreaubaaee002006-06-26 02:48:02 +02006185 linenum++;
6186
6187 end = line + strlen(line);
6188
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006189 if (end-line == sizeof(thisline)-1 && *(end-1) != '\n') {
6190 /* Check if we reached the limit and the last char is not \n.
6191 * Watch out for the last line without the terminating '\n'!
6192 */
6193 Alert("parsing [%s:%d]: line too long, limit: %d.\n",
Willy Tarreau5e4a6f12009-04-11 19:42:49 +02006194 file, linenum, (int)sizeof(thisline)-1);
Willy Tarreau058e9072009-07-20 09:30:05 +02006195 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006196 }
6197
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006199 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006200 line++;
6201
6202 arg = 0;
6203 args[arg] = line;
6204
6205 while (*line && arg < MAX_LINE_ARGS) {
6206 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6207 * C equivalent value. Other combinations left unchanged (eg: \1).
6208 */
6209 if (*line == '\\') {
6210 int skip = 0;
6211 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6212 *line = line[1];
6213 skip = 1;
6214 }
6215 else if (line[1] == 'r') {
6216 *line = '\r';
6217 skip = 1;
6218 }
6219 else if (line[1] == 'n') {
6220 *line = '\n';
6221 skip = 1;
6222 }
6223 else if (line[1] == 't') {
6224 *line = '\t';
6225 skip = 1;
6226 }
6227 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006228 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006229 unsigned char hex1, hex2;
6230 hex1 = toupper(line[2]) - '0';
6231 hex2 = toupper(line[3]) - '0';
6232 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6233 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6234 *line = (hex1<<4) + hex2;
6235 skip = 3;
6236 }
6237 else {
6238 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006239 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006240 }
6241 }
6242 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006243 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 end -= skip;
6245 }
6246 line++;
6247 }
6248 else if (*line == '#' || *line == '\n' || *line == '\r') {
6249 /* end of string, end of loop */
6250 *line = 0;
6251 break;
6252 }
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006253 else if (isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006254 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006255 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006256 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006257 line++;
6258 args[++arg] = line;
6259 }
6260 else {
6261 line++;
6262 }
6263 }
6264
6265 /* empty line */
6266 if (!**args)
6267 continue;
6268
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006269 if (*line) {
6270 /* we had to stop due to too many args.
6271 * Let's terminate the string, print the offending part then cut the
6272 * last arg.
6273 */
6274 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6275 line++;
6276 *line = '\0';
6277
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006278 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006279 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006280 err_code |= ERR_ALERT | ERR_FATAL;
6281 args[arg] = line;
6282 }
6283
Willy Tarreau540abe42007-05-02 20:50:16 +02006284 /* zero out remaining args and ensure that at least one entry
6285 * is zeroed out.
6286 */
6287 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006288 args[arg] = line;
6289 }
6290
Willy Tarreau3842f002009-06-14 11:39:52 +02006291 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006292 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006293 char *tmp;
6294
Willy Tarreau3842f002009-06-14 11:39:52 +02006295 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006296 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006297 for (arg=0; *args[arg+1]; arg++)
6298 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006299 *tmp = '\0'; // fix the next arg to \0
6300 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006301 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006302 else if (!strcmp(args[0], "default")) {
6303 kwm = KWM_DEF;
6304 for (arg=0; *args[arg+1]; arg++)
6305 args[arg] = args[arg+1]; // shift args after inversion
6306 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006307
William Lallemand0f99e342011-10-12 17:50:54 +02006308 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6309 strcmp(args[0], "log") != 0) {
6310 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006311 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006312 }
6313
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006314 /* detect section start */
6315 list_for_each_entry(ics, &sections, list) {
6316 if (strcmp(args[0], ics->section_name) == 0) {
6317 cursection = ics->section_name;
6318 cs = ics;
6319 break;
6320 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006321 }
6322
Willy Tarreaubaaee002006-06-26 02:48:02 +02006323 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006324 if (cs)
6325 err_code |= cs->section_parser(file, linenum, args, kwm);
6326 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006327 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006328 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006329 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006330
6331 if (err_code & ERR_ABORT)
6332 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006334 cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006335 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006336 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006337}
6338
Willy Tarreau64ab6072014-09-16 12:17:36 +02006339/* This function propagates processes from frontend <from> to backend <to> so
6340 * that it is always guaranteed that a backend pointed to by a frontend is
6341 * bound to all of its processes. After that, if the target is a "listen"
6342 * instance, the function recursively descends the target's own targets along
6343 * default_backend, use_backend rules, and reqsetbe rules. Since the bits are
6344 * checked first to ensure that <to> is already bound to all processes of
6345 * <from>, there is no risk of looping and we ensure to follow the shortest
6346 * path to the destination.
6347 *
6348 * It is possible to set <to> to NULL for the first call so that the function
6349 * takes care of visiting the initial frontend in <from>.
6350 *
6351 * It is important to note that the function relies on the fact that all names
6352 * have already been resolved.
6353 */
6354void propagate_processes(struct proxy *from, struct proxy *to)
6355{
6356 struct switching_rule *rule;
6357 struct hdr_exp *exp;
6358
6359 if (to) {
6360 /* check whether we need to go down */
6361 if (from->bind_proc &&
6362 (from->bind_proc & to->bind_proc) == from->bind_proc)
6363 return;
6364
6365 if (!from->bind_proc && !to->bind_proc)
6366 return;
6367
6368 to->bind_proc = from->bind_proc ?
6369 (to->bind_proc | from->bind_proc) : 0;
6370
6371 /* now propagate down */
6372 from = to;
6373 }
6374
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006375 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006376 return;
6377
Willy Tarreauf6b70012014-12-18 14:00:43 +01006378 if (from->state == PR_STSTOPPED)
6379 return;
6380
Willy Tarreau64ab6072014-09-16 12:17:36 +02006381 /* default_backend */
6382 if (from->defbe.be)
6383 propagate_processes(from, from->defbe.be);
6384
6385 /* use_backend */
6386 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006387 if (rule->dynamic)
6388 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006389 to = rule->be.backend;
6390 propagate_processes(from, to);
6391 }
6392
6393 /* reqsetbe */
6394 for (exp = from->req_exp; exp != NULL; exp = exp->next) {
6395 if (exp->action != ACT_SETBE)
6396 continue;
6397 to = (struct proxy *)exp->replace;
6398 propagate_processes(from, to);
6399 }
6400}
6401
Willy Tarreaubb925012009-07-23 13:36:36 +02006402/*
6403 * Returns the error code, 0 if OK, or any combination of :
6404 * - ERR_ABORT: must abort ASAP
6405 * - ERR_FATAL: we can continue parsing but not start the service
6406 * - ERR_WARN: a warning has been emitted
6407 * - ERR_ALERT: an alert has been emitted
6408 * Only the two first ones can stop processing, the two others are just
6409 * indicators.
6410 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006411int check_config_validity()
6412{
6413 int cfgerr = 0;
6414 struct proxy *curproxy = NULL;
6415 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006416 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006417 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006418 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006420 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006421 /*
6422 * Now, check for the integrity of all that we have collected.
6423 */
6424
6425 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02006426 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427
Willy Tarreau193b8c62012-11-22 00:17:38 +01006428 if (!global.tune.max_http_hdr)
6429 global.tune.max_http_hdr = MAX_HTTP_HDR;
6430
6431 if (!global.tune.cookie_len)
6432 global.tune.cookie_len = CAPTURE_LEN;
6433
6434 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
6435
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006436 /* Post initialisation of the users and groups lists. */
6437 err_code = userlist_postinit();
6438 if (err_code != ERR_NONE)
6439 goto out;
6440
Willy Tarreau55bc0f82009-03-15 14:51:53 +01006441 /* first, we will invert the proxy list order */
6442 curproxy = NULL;
6443 while (proxy) {
6444 struct proxy *next;
6445
6446 next = proxy->next;
6447 proxy->next = curproxy;
6448 curproxy = proxy;
6449 if (!next)
6450 break;
6451 proxy = next;
6452 }
6453
Willy Tarreau419ead82014-09-16 13:41:21 +02006454 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006455 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006456 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01006457 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006458 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02006459 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006460 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01006461 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006462
Willy Tarreau050536d2012-10-04 08:47:34 +02006463 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006464 /* proxy ID not set, use automatic numbering with first
6465 * spare entry starting with next_pxid.
6466 */
6467 next_pxid = get_next_id(&used_proxy_id, next_pxid);
6468 curproxy->conf.id.key = curproxy->uuid = next_pxid;
6469 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006470 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01006471 next_pxid++;
6472
Willy Tarreau55ea7572007-06-17 19:56:27 +02006473
Willy Tarreaubaaee002006-06-26 02:48:02 +02006474 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02006475 /* ensure we don't keep listeners uselessly bound */
6476 stop_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 continue;
6478 }
6479
Willy Tarreau102df612014-05-07 23:56:38 +02006480 /* Check multi-process mode compatibility for the current proxy */
6481
6482 if (curproxy->bind_proc) {
6483 /* an explicit bind-process was specified, let's check how many
6484 * processes remain.
6485 */
6486 nbproc = popcount(curproxy->bind_proc);
6487
6488 curproxy->bind_proc &= nbits(global.nbproc);
6489 if (!curproxy->bind_proc && nbproc == 1) {
6490 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);
6491 curproxy->bind_proc = 1;
6492 }
6493 else if (!curproxy->bind_proc && nbproc > 1) {
6494 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);
6495 curproxy->bind_proc = 0;
6496 }
6497 }
6498
Willy Tarreau3d209582014-05-09 17:06:11 +02006499 /* check and reduce the bind-proc of each listener */
6500 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
6501 unsigned long mask;
6502
6503 if (!bind_conf->bind_proc)
6504 continue;
6505
6506 mask = nbits(global.nbproc);
6507 if (curproxy->bind_proc)
6508 mask &= curproxy->bind_proc;
6509 /* mask cannot be null here thanks to the previous checks */
6510
6511 nbproc = popcount(bind_conf->bind_proc);
6512 bind_conf->bind_proc &= mask;
6513
6514 if (!bind_conf->bind_proc && nbproc == 1) {
6515 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",
6516 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6517 bind_conf->bind_proc = mask & ~(mask - 1);
6518 }
6519 else if (!bind_conf->bind_proc && nbproc > 1) {
6520 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",
6521 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
6522 bind_conf->bind_proc = 0;
6523 }
6524 }
6525
Willy Tarreau102df612014-05-07 23:56:38 +02006526 if (global.nbproc > 1 && curproxy->table.peers.name) {
6527 Alert("Proxy '%s': peers can't be used in multi-process mode (nbproc > 1).\n",
6528 curproxy->id);
6529 cfgerr++;
6530 }
Willy Tarreau16a21472012-11-19 12:39:59 +01006531
Willy Tarreauff01a212009-03-15 13:46:16 +01006532 switch (curproxy->mode) {
6533 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006534 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006535 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006536 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
6537 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006538 cfgerr++;
6539 }
6540
6541 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006542 Warning("config : servers will be ignored for %s '%s'.\n",
6543 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01006544 break;
6545
6546 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006547 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01006548 break;
6549
6550 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01006551 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01006552 break;
6553 }
6554
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006555 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02006556 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006557 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006558 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
6559 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006560 cfgerr++;
6561 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006562#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006563 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006564 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
6565 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006566 cfgerr++;
6567 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02006569 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006570 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
6571 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02006572 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006573 }
6574 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02006575 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01006576 /* If no LB algo is set in a backend, and we're not in
6577 * transparent mode, dispatch mode nor proxy mode, we
6578 * want to use balance roundrobin by default.
6579 */
6580 curproxy->lbprm.algo &= ~BE_LB_ALGO;
6581 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006582 }
6583 }
Willy Tarreau193cf932007-09-17 10:17:23 +02006584
Willy Tarreau1620ec32011-08-06 17:05:02 +02006585 if (curproxy->options & PR_O_DISPATCH)
6586 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
6587 else if (curproxy->options & PR_O_HTTP_PROXY)
6588 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
6589 else if (curproxy->options & PR_O_TRANSP)
6590 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01006591
Willy Tarreau1620ec32011-08-06 17:05:02 +02006592 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
6593 if (curproxy->options & PR_O_DISABLE404) {
6594 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6595 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
6596 err_code |= ERR_WARN;
6597 curproxy->options &= ~PR_O_DISABLE404;
6598 }
6599 if (curproxy->options2 & PR_O2_CHK_SNDST) {
6600 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
6601 "send-state", proxy_type_str(curproxy), curproxy->id);
6602 err_code |= ERR_WARN;
6603 curproxy->options &= ~PR_O2_CHK_SNDST;
6604 }
Willy Tarreauef781042010-01-27 11:53:01 +01006605 }
6606
Simon Horman98637e52014-06-20 12:30:16 +09006607 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
6608 if (!global.external_check) {
6609 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
6610 curproxy->id, "option external-check");
6611 cfgerr++;
6612 }
6613 if (!curproxy->check_command) {
6614 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
6615 curproxy->id, "option external-check");
6616 cfgerr++;
6617 }
6618 }
6619
Simon Horman64e34162015-02-06 11:11:57 +09006620 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006621 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
6622 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09006623 "'email-alert from', 'email-alert level' 'email-alert mailer', "
6624 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09006625 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
6626 "to be present).\n",
6627 proxy_type_str(curproxy), curproxy->id);
6628 err_code |= ERR_WARN;
6629 free_email_alert(curproxy);
6630 }
6631 if (!curproxy->email_alert.myhostname)
6632 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09006633 }
6634
Simon Horman98637e52014-06-20 12:30:16 +09006635 if (curproxy->check_command) {
6636 int clear = 0;
6637 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6638 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6639 "external-check command", proxy_type_str(curproxy), curproxy->id);
6640 err_code |= ERR_WARN;
6641 clear = 1;
6642 }
6643 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
6644 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
6645 curproxy->id, "external-check command");
6646 cfgerr++;
6647 }
6648 if (clear) {
6649 free(curproxy->check_command);
6650 curproxy->check_command = NULL;
6651 }
6652 }
6653
6654 if (curproxy->check_path) {
6655 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
6656 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
6657 "external-check path", proxy_type_str(curproxy), curproxy->id);
6658 err_code |= ERR_WARN;
6659 free(curproxy->check_path);
6660 curproxy->check_path = NULL;
6661 }
6662 }
6663
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006664 /* if a default backend was specified, let's find it */
6665 if (curproxy->defbe.name) {
6666 struct proxy *target;
6667
Alex Williams96532db2009-11-01 21:27:13 -05006668 target = findproxy_mode(curproxy->defbe.name, curproxy->mode, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006669 if (!target) {
6670 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
6671 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006672 cfgerr++;
6673 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006674 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
6675 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02006676 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006677 } else {
6678 free(curproxy->defbe.name);
6679 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01006680
6681 /* Emit a warning if this proxy also has some servers */
6682 if (curproxy->srv) {
6683 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
6684 curproxy->id);
6685 err_code |= ERR_WARN;
6686 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006687 }
6688 }
6689
Willy Tarreau5fdfb912007-01-01 23:11:07 +01006690 /* find the target proxy in setbe */
Willy Tarreaua496b602006-12-17 23:15:24 +01006691 if (curproxy->mode == PR_MODE_HTTP && curproxy->req_exp != NULL) {
6692 /* map jump target for ACT_SETBE in req_rep chain */
6693 struct hdr_exp *exp;
Willy Tarreaua496b602006-12-17 23:15:24 +01006694 for (exp = curproxy->req_exp; exp != NULL; exp = exp->next) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006695 struct proxy *target;
6696
Willy Tarreaua496b602006-12-17 23:15:24 +01006697 if (exp->action != ACT_SETBE)
6698 continue;
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006699
Alex Williams96532db2009-11-01 21:27:13 -05006700 target = findproxy_mode(exp->replace, PR_MODE_HTTP, PR_CAP_BE);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006701 if (!target) {
6702 Alert("Proxy '%s': unable to find required setbe: '%s'.\n",
6703 curproxy->id, exp->replace);
Willy Tarreaua496b602006-12-17 23:15:24 +01006704 cfgerr++;
6705 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006706 Alert("Proxy '%s': loop detected for setbe: '%s'.\n",
6707 curproxy->id, exp->replace);
Willy Tarreau977b8e42006-12-29 14:19:17 +01006708 cfgerr++;
Willy Tarreaua496b602006-12-17 23:15:24 +01006709 } else {
6710 free((void *)exp->replace);
6711 exp->replace = (const char *)target;
6712 }
6713 }
6714 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02006715
6716 /* find the target proxy for 'use_backend' rules */
6717 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02006718 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01006719 struct logformat_node *node;
6720 char *pxname;
6721
6722 /* Try to parse the string as a log format expression. If the result
6723 * of the parsing is only one entry containing a simple string, then
6724 * it's a standard string corresponding to a static rule, thus the
6725 * parsing is cancelled and be.name is restored to be resolved.
6726 */
6727 pxname = rule->be.name;
6728 LIST_INIT(&rule->be.expr);
6729 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
6730 curproxy->conf.args.file, curproxy->conf.args.line);
6731 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
6732
6733 if (!LIST_ISEMPTY(&rule->be.expr)) {
6734 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
6735 rule->dynamic = 1;
6736 free(pxname);
6737 continue;
6738 }
6739 /* simple string: free the expression and fall back to static rule */
6740 free(node->arg);
6741 free(node);
6742 }
6743
6744 rule->dynamic = 0;
6745 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006746
Alex Williams96532db2009-11-01 21:27:13 -05006747 target = findproxy_mode(rule->be.name, curproxy->mode, PR_CAP_BE);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006748
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006749 if (!target) {
6750 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
6751 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006752 cfgerr++;
6753 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01006754 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
6755 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02006756 cfgerr++;
6757 } else {
6758 free((void *)rule->be.name);
6759 rule->be.backend = target;
6760 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006761 }
6762
Willy Tarreau64ab6072014-09-16 12:17:36 +02006763 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02006764 list_for_each_entry(srule, &curproxy->server_rules, list) {
6765 struct server *target = findserver(curproxy, srule->srv.name);
6766
6767 if (!target) {
6768 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
6769 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
6770 cfgerr++;
6771 continue;
6772 }
6773 free((void *)srule->srv.name);
6774 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02006775 }
6776
Emeric Brunb982a3d2010-01-04 15:45:53 +01006777 /* find the target table for 'stick' rules */
6778 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
6779 struct proxy *target;
6780
Emeric Brun1d33b292010-01-04 15:47:17 +01006781 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
6782 if (mrule->flags & STK_IS_STORE)
6783 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6784
Emeric Brunb982a3d2010-01-04 15:45:53 +01006785 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006786 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006787 else
6788 target = curproxy;
6789
6790 if (!target) {
6791 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
6792 curproxy->id, mrule->table.name);
6793 cfgerr++;
6794 }
6795 else if (target->table.size == 0) {
6796 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6797 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6798 cfgerr++;
6799 }
Willy Tarreau12785782012-04-27 21:37:17 +02006800 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6801 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006802 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6803 cfgerr++;
6804 }
6805 else {
6806 free((void *)mrule->table.name);
6807 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006808 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006809 }
6810 }
6811
6812 /* find the target table for 'store response' rules */
6813 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
6814 struct proxy *target;
6815
Emeric Brun1d33b292010-01-04 15:47:17 +01006816 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
6817
Emeric Brunb982a3d2010-01-04 15:45:53 +01006818 if (mrule->table.name)
Willy Tarreauc00cdc22010-06-06 16:48:26 +02006819 target = findproxy(mrule->table.name, 0);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006820 else
6821 target = curproxy;
6822
6823 if (!target) {
6824 Alert("Proxy '%s': unable to find store table '%s'.\n",
6825 curproxy->id, mrule->table.name);
6826 cfgerr++;
6827 }
6828 else if (target->table.size == 0) {
6829 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
6830 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6831 cfgerr++;
6832 }
Willy Tarreau12785782012-04-27 21:37:17 +02006833 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
6834 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01006835 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
6836 cfgerr++;
6837 }
6838 else {
6839 free((void *)mrule->table.name);
6840 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02006841 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01006842 }
6843 }
6844
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006845 /* find the target table for 'tcp-request' layer 4 rules */
6846 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
6847 struct proxy *target;
6848
Willy Tarreaub4c84932013-07-23 19:15:30 +02006849 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006850 continue;
6851
6852 if (trule->act_prm.trk_ctr.table.n)
6853 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6854 else
6855 target = curproxy;
6856
6857 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006858 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6859 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006860 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006861 cfgerr++;
6862 }
6863 else if (target->table.size == 0) {
6864 Alert("Proxy '%s': table '%s' used but not configured.\n",
6865 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6866 cfgerr++;
6867 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006868 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6869 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6870 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 +01006871 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006872 cfgerr++;
6873 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006874 else {
6875 free(trule->act_prm.trk_ctr.table.n);
6876 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006877 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02006878 * to pass a list of counters to track and allocate them right here using
6879 * stktable_alloc_data_type().
6880 */
6881 }
6882 }
6883
Willy Tarreaud1f96522010-08-03 19:34:32 +02006884 /* find the target table for 'tcp-request' layer 6 rules */
6885 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
6886 struct proxy *target;
6887
Willy Tarreaub4c84932013-07-23 19:15:30 +02006888 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02006889 continue;
6890
6891 if (trule->act_prm.trk_ctr.table.n)
6892 target = findproxy(trule->act_prm.trk_ctr.table.n, 0);
6893 else
6894 target = curproxy;
6895
6896 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02006897 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6898 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01006899 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02006900 cfgerr++;
6901 }
6902 else if (target->table.size == 0) {
6903 Alert("Proxy '%s': table '%s' used but not configured.\n",
6904 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
6905 cfgerr++;
6906 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01006907 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
6908 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6909 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 +01006910 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01006911 cfgerr++;
6912 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02006913 else {
6914 free(trule->act_prm.trk_ctr.table.n);
6915 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02006916 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02006917 * to pass a list of counters to track and allocate them right here using
6918 * stktable_alloc_data_type().
6919 */
6920 }
6921 }
6922
Willy Tarreau09448f72014-06-25 18:12:15 +02006923 /* find the target table for 'http-request' layer 7 rules */
6924 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
6925 struct proxy *target;
6926
6927 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
6928 continue;
6929
6930 if (hrqrule->act_prm.trk_ctr.table.n)
6931 target = findproxy(hrqrule->act_prm.trk_ctr.table.n, 0);
6932 else
6933 target = curproxy;
6934
6935 if (!target) {
6936 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
6937 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
6938 http_req_trk_idx(hrqrule->action));
6939 cfgerr++;
6940 }
6941 else if (target->table.size == 0) {
6942 Alert("Proxy '%s': table '%s' used but not configured.\n",
6943 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
6944 cfgerr++;
6945 }
6946 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
6947 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
6948 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
6949 http_req_trk_idx(hrqrule->action));
6950 cfgerr++;
6951 }
6952 else {
6953 free(hrqrule->act_prm.trk_ctr.table.n);
6954 hrqrule->act_prm.trk_ctr.table.t = &target->table;
6955 /* Note: if we decide to enhance the track-sc syntax, we may be able
6956 * to pass a list of counters to track and allocate them right here using
6957 * stktable_alloc_data_type().
6958 */
6959 }
6960 }
6961
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02006962 /* move any "block" rules at the beginning of the http-request rules */
6963 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
6964 /* insert block_rules into http_req_rules at the beginning */
6965 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
6966 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
6967 curproxy->block_rules.n->p = &curproxy->http_req_rules;
6968 curproxy->http_req_rules.n = curproxy->block_rules.n;
6969 LIST_INIT(&curproxy->block_rules);
6970 }
6971
Emeric Brun32da3c42010-09-23 18:39:19 +02006972 if (curproxy->table.peers.name) {
6973 struct peers *curpeers = peers;
6974
6975 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
6976 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
6977 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01006978 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02006979 break;
6980 }
6981 }
6982
6983 if (!curpeers) {
6984 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
6985 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006986 free((void *)curproxy->table.peers.name);
6987 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006988 cfgerr++;
6989 }
6990 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02006991 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
6992 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02006993 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02006994 cfgerr++;
6995 }
6996 }
6997
Simon Horman9dc49962015-01-30 11:22:59 +09006998
6999 if (curproxy->email_alert.mailers.name) {
7000 struct mailers *curmailers = mailers;
7001
7002 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7003 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7004 free(curproxy->email_alert.mailers.name);
7005 curproxy->email_alert.mailers.m = curmailers;
7006 curmailers->users++;
7007 break;
7008 }
7009 }
7010
7011 if (!curmailers) {
7012 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7013 curproxy->id, curproxy->email_alert.mailers.name);
7014 free_email_alert(curproxy);
7015 cfgerr++;
7016 }
7017 }
7018
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007019 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007020 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007021 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7022 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7023 "proxy", curproxy->id);
7024 cfgerr++;
7025 goto out_uri_auth_compat;
7026 }
7027
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007028 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007029 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007030 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007031 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007032
Willy Tarreau95fa4692010-02-01 13:05:50 +01007033 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7034 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007035
7036 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007037 uri_auth_compat_req[i++] = "realm";
7038 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7039 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007040
Willy Tarreau95fa4692010-02-01 13:05:50 +01007041 uri_auth_compat_req[i++] = "unless";
7042 uri_auth_compat_req[i++] = "{";
7043 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7044 uri_auth_compat_req[i++] = "}";
7045 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007046
Willy Tarreauff011f22011-01-06 17:51:27 +01007047 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7048 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007049 cfgerr++;
7050 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007051 }
7052
Willy Tarreauff011f22011-01-06 17:51:27 +01007053 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007054
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007055 if (curproxy->uri_auth->auth_realm) {
7056 free(curproxy->uri_auth->auth_realm);
7057 curproxy->uri_auth->auth_realm = NULL;
7058 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007059
7060 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007061 }
7062out_uri_auth_compat:
7063
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007064 /* compile the log format */
7065 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007066 if (curproxy->conf.logformat_string != default_http_log_format &&
7067 curproxy->conf.logformat_string != default_tcp_log_format &&
7068 curproxy->conf.logformat_string != clf_http_log_format)
7069 free(curproxy->conf.logformat_string);
7070 curproxy->conf.logformat_string = NULL;
7071 free(curproxy->conf.lfs_file);
7072 curproxy->conf.lfs_file = NULL;
7073 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007074 }
7075
Willy Tarreau62a61232013-04-12 18:13:46 +02007076 if (curproxy->conf.logformat_string) {
7077 curproxy->conf.args.ctx = ARGC_LOG;
7078 curproxy->conf.args.file = curproxy->conf.lfs_file;
7079 curproxy->conf.args.line = curproxy->conf.lfs_line;
7080 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007081 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007082 curproxy->conf.args.file = NULL;
7083 curproxy->conf.args.line = 0;
7084 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007085
Willy Tarreau62a61232013-04-12 18:13:46 +02007086 if (curproxy->conf.uniqueid_format_string) {
7087 curproxy->conf.args.ctx = ARGC_UIF;
7088 curproxy->conf.args.file = curproxy->conf.uif_file;
7089 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007090 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007091 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007092 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007093 curproxy->conf.args.file = NULL;
7094 curproxy->conf.args.line = 0;
7095 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007096
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007097 /* only now we can check if some args remain unresolved.
7098 * This must be done after the users and groups resolution.
7099 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007100 cfgerr += smp_resolve_args(curproxy);
7101 if (!cfgerr)
7102 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007103
Willy Tarreau2738a142006-07-08 17:28:09 +02007104 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007105 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007106 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007107 (!curproxy->timeout.connect ||
7108 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007109 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007110 " | While not properly invalid, you will certainly encounter various problems\n"
7111 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007112 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007113 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007114 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007115 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007116
Willy Tarreau1fa31262007-12-03 00:36:16 +01007117 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7118 * We must still support older configurations, so let's find out whether those
7119 * parameters have been set or must be copied from contimeouts.
7120 */
7121 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007122 if (!curproxy->timeout.tarpit ||
7123 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007124 /* tarpit timeout not set. We search in the following order:
7125 * default.tarpit, curr.connect, default.connect.
7126 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007127 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007128 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007129 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007130 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007131 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007132 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007133 }
7134 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007135 (!curproxy->timeout.queue ||
7136 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007137 /* queue timeout not set. We search in the following order:
7138 * default.queue, curr.connect, default.connect.
7139 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007140 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007141 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007142 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007143 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007144 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007145 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007146 }
7147 }
7148
Willy Tarreau1620ec32011-08-06 17:05:02 +02007149 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007150 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7151 curproxy->check_req = (char *)malloc(curproxy->check_len);
7152 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007153 }
7154
Willy Tarreau215663d2014-06-13 18:30:23 +02007155 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7156 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7157 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7158 proxy_type_str(curproxy), curproxy->id);
7159 err_code |= ERR_WARN;
7160 }
7161
Willy Tarreau193b8c62012-11-22 00:17:38 +01007162 /* ensure that cookie capture length is not too large */
7163 if (curproxy->capture_len >= global.tune.cookie_len) {
7164 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7165 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7166 err_code |= ERR_WARN;
7167 curproxy->capture_len = global.tune.cookie_len - 1;
7168 }
7169
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007170 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007171 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007172 curproxy->req_cap_pool = create_pool("ptrcap",
7173 curproxy->nb_req_cap * sizeof(char *),
7174 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007175 }
7176
7177 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007178 curproxy->rsp_cap_pool = create_pool("ptrcap",
7179 curproxy->nb_rsp_cap * sizeof(char *),
7180 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007181 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007182
Willy Tarreaubaaee002006-06-26 02:48:02 +02007183 /* first, we will invert the servers list order */
7184 newsrv = NULL;
7185 while (curproxy->srv) {
7186 struct server *next;
7187
7188 next = curproxy->srv->next;
7189 curproxy->srv->next = newsrv;
7190 newsrv = curproxy->srv;
7191 if (!next)
7192 break;
7193 curproxy->srv = next;
7194 }
7195
Willy Tarreau17edc812014-01-03 12:14:34 +01007196 /* Check that no server name conflicts. This causes trouble in the stats.
7197 * We only emit a warning for the first conflict affecting each server,
7198 * in order to avoid combinatory explosion if all servers have the same
7199 * name. We do that only for servers which do not have an explicit ID,
7200 * because these IDs were made also for distinguishing them and we don't
7201 * want to annoy people who correctly manage them.
7202 */
7203 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7204 struct server *other_srv;
7205
7206 if (newsrv->puid)
7207 continue;
7208
7209 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7210 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7211 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7212 newsrv->conf.file, newsrv->conf.line,
7213 proxy_type_str(curproxy), curproxy->id,
7214 newsrv->id, other_srv->conf.line);
7215 break;
7216 }
7217 }
7218 }
7219
Willy Tarreaudd701652010-05-25 23:03:02 +02007220 /* assign automatic UIDs to servers which don't have one yet */
7221 next_id = 1;
7222 newsrv = curproxy->srv;
7223 while (newsrv != NULL) {
7224 if (!newsrv->puid) {
7225 /* server ID not set, use automatic numbering with first
7226 * spare entry starting with next_svid.
7227 */
7228 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7229 newsrv->conf.id.key = newsrv->puid = next_id;
7230 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7231 }
7232 next_id++;
7233 newsrv = newsrv->next;
7234 }
7235
Willy Tarreau20697042007-11-15 23:26:18 +01007236 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007237 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007238
Willy Tarreau62c3be22012-01-20 13:12:32 +01007239 /*
7240 * If this server supports a maxconn parameter, it needs a dedicated
7241 * tasks to fill the emptied slots when a connection leaves.
7242 * Also, resolve deferred tracking dependency if needed.
7243 */
7244 newsrv = curproxy->srv;
7245 while (newsrv != NULL) {
7246 if (newsrv->minconn > newsrv->maxconn) {
7247 /* Only 'minconn' was specified, or it was higher than or equal
7248 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7249 * this will avoid further useless expensive computations.
7250 */
7251 newsrv->maxconn = newsrv->minconn;
7252 } else if (newsrv->maxconn && !newsrv->minconn) {
7253 /* minconn was not specified, so we set it to maxconn */
7254 newsrv->minconn = newsrv->maxconn;
7255 }
7256
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007257#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007258 if (newsrv->use_ssl || newsrv->check.use_ssl)
7259 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007260#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007261
Willy Tarreau2f075e92013-12-03 11:11:34 +01007262 /* set the check type on the server */
7263 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7264
Willy Tarreau62c3be22012-01-20 13:12:32 +01007265 if (newsrv->trackit) {
7266 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007267 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007268 char *pname, *sname;
7269
7270 pname = newsrv->trackit;
7271 sname = strrchr(pname, '/');
7272
7273 if (sname)
7274 *sname++ = '\0';
7275 else {
7276 sname = pname;
7277 pname = NULL;
7278 }
7279
7280 if (pname) {
7281 px = findproxy(pname, PR_CAP_BE);
7282 if (!px) {
7283 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7284 proxy_type_str(curproxy), curproxy->id,
7285 newsrv->id, pname);
7286 cfgerr++;
7287 goto next_srv;
7288 }
7289 } else
7290 px = curproxy;
7291
7292 srv = findserver(px, sname);
7293 if (!srv) {
7294 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7295 proxy_type_str(curproxy), curproxy->id,
7296 newsrv->id, sname);
7297 cfgerr++;
7298 goto next_srv;
7299 }
7300
Willy Tarreau32091232014-05-16 13:52:00 +02007301 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7302 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7303 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007304 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007305 "tracking as it does not have any check nor agent enabled.\n",
7306 proxy_type_str(curproxy), curproxy->id,
7307 newsrv->id, px->id, srv->id);
7308 cfgerr++;
7309 goto next_srv;
7310 }
7311
7312 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7313
7314 if (loop) {
7315 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7316 "belongs to a tracking chain looping back to %s/%s.\n",
7317 proxy_type_str(curproxy), curproxy->id,
7318 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007319 cfgerr++;
7320 goto next_srv;
7321 }
7322
7323 if (curproxy != px &&
7324 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7325 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7326 "tracking: disable-on-404 option inconsistency.\n",
7327 proxy_type_str(curproxy), curproxy->id,
7328 newsrv->id, px->id, srv->id);
7329 cfgerr++;
7330 goto next_srv;
7331 }
7332
7333 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007334 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007335 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007336 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007337 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007338 }
7339
7340 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007341 newsrv->tracknext = srv->trackers;
7342 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007343
7344 free(newsrv->trackit);
7345 newsrv->trackit = NULL;
7346 }
7347 next_srv:
7348 newsrv = newsrv->next;
7349 }
7350
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007351 /* We have to initialize the server lookup mechanism depending
7352 * on what LB algorithm was choosen.
7353 */
7354
7355 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7356 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7357 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007358 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7359 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7360 init_server_map(curproxy);
7361 } else {
7362 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7363 fwrr_init_server_groups(curproxy);
7364 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007365 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007366
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007367 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007368 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7369 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7370 fwlc_init_server_tree(curproxy);
7371 } else {
7372 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7373 fas_init_server_tree(curproxy);
7374 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007375 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007376
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007377 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007378 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7379 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7380 chash_init_server_tree(curproxy);
7381 } else {
7382 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7383 init_server_map(curproxy);
7384 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007385 break;
7386 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007387
7388 if (curproxy->options & PR_O_LOGASAP)
7389 curproxy->to_log &= ~LW_BYTES;
7390
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007391 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007392 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007393 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7394 proxy_type_str(curproxy), curproxy->id);
7395 err_code |= ERR_WARN;
7396 }
7397
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007398 if (curproxy->mode != PR_MODE_HTTP) {
7399 int optnum;
7400
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007401 if (curproxy->uri_auth) {
7402 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7403 proxy_type_str(curproxy), curproxy->id);
7404 err_code |= ERR_WARN;
7405 curproxy->uri_auth = NULL;
7406 }
7407
Willy Tarreau87cf5142011-08-19 22:57:24 +02007408 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007409 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7410 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7411 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007412 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007413 }
7414
7415 if (curproxy->options & PR_O_ORGTO) {
7416 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7417 "originalto", proxy_type_str(curproxy), curproxy->id);
7418 err_code |= ERR_WARN;
7419 curproxy->options &= ~PR_O_ORGTO;
7420 }
7421
7422 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7423 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7424 (curproxy->cap & cfg_opts[optnum].cap) &&
7425 (curproxy->options & cfg_opts[optnum].val)) {
7426 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7427 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
7428 err_code |= ERR_WARN;
7429 curproxy->options &= ~cfg_opts[optnum].val;
7430 }
7431 }
7432
7433 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
7434 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
7435 (curproxy->cap & cfg_opts2[optnum].cap) &&
7436 (curproxy->options2 & cfg_opts2[optnum].val)) {
7437 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7438 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
7439 err_code |= ERR_WARN;
7440 curproxy->options2 &= ~cfg_opts2[optnum].val;
7441 }
7442 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007443
Pieter Baauwd551fb52013-05-08 22:49:23 +02007444#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007445 if (curproxy->conn_src.bind_hdr_occ) {
7446 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007447 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01007448 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007449 err_code |= ERR_WARN;
7450 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007451#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007452 }
7453
Willy Tarreaubaaee002006-06-26 02:48:02 +02007454 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01007455 * ensure that we're not cross-dressing a TCP server into HTTP.
7456 */
7457 newsrv = curproxy->srv;
7458 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01007459 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007460 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
7461 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007462 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01007463 }
Willy Tarreaubce70882009-09-07 11:51:47 +02007464
Willy Tarreau0cec3312011-10-31 13:49:26 +01007465 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
7466 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
7467 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7468 err_code |= ERR_WARN;
7469 }
7470
Willy Tarreauc93cd162014-05-13 15:54:22 +02007471 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02007472 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
7473 proxy_type_str(curproxy), curproxy->id, newsrv->id);
7474 err_code |= ERR_WARN;
7475 }
7476
Pieter Baauwd551fb52013-05-08 22:49:23 +02007477#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01007478 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
7479 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02007480 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 +01007481 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02007482 err_code |= ERR_WARN;
7483 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02007484#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01007485 newsrv = newsrv->next;
7486 }
7487
Willy Tarreaue42bd962014-09-16 16:21:19 +02007488 /* check if we have a frontend with "tcp-request content" looking at L7
7489 * with no inspect-delay
7490 */
7491 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
7492 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7493 if (trule->action == TCP_ACT_CAPTURE &&
7494 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7495 break;
7496 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
7497 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
7498 break;
7499 }
7500
7501 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
7502 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
7503 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
7504 " This means that these rules will randomly find their contents. This can be fixed by"
7505 " setting the tcp-request inspect-delay.\n",
7506 proxy_type_str(curproxy), curproxy->id);
7507 err_code |= ERR_WARN;
7508 }
7509 }
7510
Willy Tarreauc1a21672009-08-16 22:37:44 +02007511 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02007512 if (!curproxy->accept)
7513 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007514
Willy Tarreauc1a21672009-08-16 22:37:44 +02007515 if (curproxy->tcp_req.inspect_delay ||
7516 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02007517 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007518
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007519 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007520 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007521 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007522 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007523
7524 /* both TCP and HTTP must check switching rules */
7525 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
7526 }
7527
7528 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02007529 if (curproxy->tcp_req.inspect_delay ||
7530 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
7531 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
7532
Emeric Brun97679e72010-09-23 17:56:44 +02007533 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
7534 curproxy->be_rsp_ana |= AN_RES_INSPECT;
7535
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007536 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02007537 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02007538 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02007539 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02007540
7541 /* If the backend does requires RDP cookie persistence, we have to
7542 * enable the corresponding analyser.
7543 */
7544 if (curproxy->options2 & PR_O2_RDPC_PRST)
7545 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
7546 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007547 }
7548
7549 /***********************************************************/
7550 /* At this point, target names have already been resolved. */
7551 /***********************************************************/
7552
7553 /* Check multi-process mode compatibility */
7554
7555 if (global.nbproc > 1 && global.stats_fe) {
7556 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7557 unsigned long mask;
7558
7559 mask = nbits(global.nbproc);
7560 if (global.stats_fe->bind_proc)
7561 mask &= global.stats_fe->bind_proc;
7562
7563 if (bind_conf->bind_proc)
7564 mask &= bind_conf->bind_proc;
7565
7566 /* stop here if more than one process is used */
7567 if (popcount(mask) > 1)
7568 break;
7569 }
7570 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
7571 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");
7572 }
7573 }
7574
7575 /* Make each frontend inherit bind-process from its listeners when not specified. */
7576 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7577 if (curproxy->bind_proc)
7578 continue;
7579
7580 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7581 unsigned long mask;
7582
7583 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7584 curproxy->bind_proc |= mask;
7585 }
7586
7587 if (!curproxy->bind_proc)
7588 curproxy->bind_proc = ~0UL;
7589 }
7590
7591 if (global.stats_fe) {
7592 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
7593 unsigned long mask;
7594
7595 mask = bind_conf->bind_proc ? bind_conf->bind_proc : ~0UL;
7596 global.stats_fe->bind_proc |= mask;
7597 }
7598 if (!global.stats_fe->bind_proc)
7599 global.stats_fe->bind_proc = ~0UL;
7600 }
7601
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02007602 /* propagate bindings from frontends to backends. Don't do it if there
7603 * are any fatal errors as we must not call it with unresolved proxies.
7604 */
7605 if (!cfgerr) {
7606 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7607 if (curproxy->cap & PR_CAP_FE)
7608 propagate_processes(curproxy, NULL);
7609 }
Willy Tarreau419ead82014-09-16 13:41:21 +02007610 }
7611
7612 /* Bind each unbound backend to all processes when not specified. */
7613 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7614 if (curproxy->bind_proc)
7615 continue;
7616 curproxy->bind_proc = ~0UL;
7617 }
7618
7619 /*******************************************************/
7620 /* At this step, all proxies have a non-null bind_proc */
7621 /*******************************************************/
7622
7623 /* perform the final checks before creating tasks */
7624
7625 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7626 struct listener *listener;
7627 unsigned int next_id;
7628 int nbproc;
7629
7630 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02007631
Emeric Brunc52962f2012-11-15 18:28:02 +01007632#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007633 /* Configure SSL for each bind line.
7634 * Note: if configuration fails at some point, the ->ctx member
7635 * remains NULL so that listeners can later detach.
7636 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007637 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007638 int alloc_ctx;
7639
Emeric Brunc52962f2012-11-15 18:28:02 +01007640 if (!bind_conf->is_ssl) {
7641 if (bind_conf->default_ctx) {
7642 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
7643 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7644 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007645 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01007646 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007647 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02007648 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007649 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007650 cfgerr++;
7651 continue;
7652 }
7653
Emeric Brun8dc60392014-05-09 13:52:00 +02007654 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007655 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02007656 if (alloc_ctx == SHCTX_E_INIT_LOCK)
7657 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");
7658 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02007659 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02007660 cfgerr++;
7661 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007662 }
7663
Emeric Brunfc0421f2012-09-07 17:30:07 +02007664 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007665 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007666 }
Emeric Brunc52962f2012-11-15 18:28:02 +01007667#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007668
Willy Tarreaue6b98942007-10-29 01:09:36 +01007669 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007670 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02007671 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007672 if (!listener->luid) {
7673 /* listener ID not set, use automatic numbering with first
7674 * spare entry starting with next_luid.
7675 */
7676 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
7677 listener->conf.id.key = listener->luid = next_id;
7678 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007679 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007680 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007681
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007682 /* enable separate counters */
7683 if (curproxy->options2 & PR_O2_SOCKSTAT) {
7684 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01007685 if (!listener->name)
7686 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02007687 }
Willy Tarreau81796be2012-09-22 19:11:47 +02007688
Willy Tarreaue6b98942007-10-29 01:09:36 +01007689 if (curproxy->options & PR_O_TCP_NOLING)
7690 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02007691 if (!listener->maxconn)
7692 listener->maxconn = curproxy->maxconn;
7693 if (!listener->backlog)
7694 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01007695 if (!listener->maxaccept)
7696 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
7697
7698 /* we want to have an optimal behaviour on single process mode to
7699 * maximize the work at once, but in multi-process we want to keep
7700 * some fairness between processes, so we target half of the max
7701 * number of events to be balanced over all the processes the proxy
7702 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
7703 * used to disable the limit.
7704 */
7705 if (listener->maxaccept > 0) {
7706 if (nbproc > 1)
7707 listener->maxaccept = (listener->maxaccept + 1) / 2;
7708 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
7709 }
7710
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007711 listener->timeout = &curproxy->timeout.client;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02007712 listener->accept = session_accept;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007713 listener->handler = process_session;
Willy Tarreauc1a21672009-08-16 22:37:44 +02007714 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau3bc13772008-12-07 11:50:35 +01007715
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02007716 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
7717 listener->options |= LI_O_TCP_RULES;
7718
Willy Tarreaude3041d2010-05-31 10:56:17 +02007719 if (curproxy->mon_mask.s_addr)
7720 listener->options |= LI_O_CHK_MONNET;
7721
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007722 /* smart accept mode is automatic in HTTP mode */
7723 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007724 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02007725 !(curproxy->no_options2 & PR_O2_SMARTACC)))
7726 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01007727 }
7728
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007729 /* Release unused SSL configs */
7730 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7731 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007732 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007733#ifdef USE_OPENSSL
7734 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007735 free(bind_conf->ca_file);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007736 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02007737 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02007738 free(bind_conf->crl_file);
Nenad Merdanovic05552d42015-02-27 19:56:49 +01007739 free(bind_conf->tls_ticket_keys);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007740#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007741 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02007742
Willy Tarreau102df612014-05-07 23:56:38 +02007743 if (nbproc > 1) {
7744 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02007745 int count, maxproc = 0;
7746
7747 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7748 count = popcount(bind_conf->bind_proc);
7749 if (count > maxproc)
7750 maxproc = count;
7751 }
7752 /* backends have 0, frontends have 1 or more */
7753 if (maxproc != 1)
7754 Warning("Proxy '%s': in multi-process mode, stats will be"
7755 " limited to process assigned to the current request.\n",
7756 curproxy->id);
7757
Willy Tarreau102df612014-05-07 23:56:38 +02007758 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
7759 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
7760 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007761 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007762 }
Willy Tarreau102df612014-05-07 23:56:38 +02007763 if (curproxy->appsession_name) {
7764 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
7765 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007766 }
Willy Tarreau102df612014-05-07 23:56:38 +02007767 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
7768 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
7769 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01007770 }
7771 }
Willy Tarreau918ff602011-07-25 16:33:49 +02007772
7773 /* create the task associated with the proxy */
7774 curproxy->task = task_new();
7775 if (curproxy->task) {
7776 curproxy->task->context = curproxy;
7777 curproxy->task->process = manage_proxy;
7778 /* no need to queue, it will be done automatically if some
7779 * listener gets limited.
7780 */
7781 curproxy->task->expire = TICK_ETERNITY;
7782 } else {
7783 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
7784 curproxy->id);
7785 cfgerr++;
7786 }
Willy Tarreaub369a042014-09-16 13:21:03 +02007787 }
7788
Willy Tarreaufbb78422011-06-05 15:38:35 +02007789 /* automatically compute fullconn if not set. We must not do it in the
7790 * loop above because cross-references are not yet fully resolved.
7791 */
7792 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
7793 /* If <fullconn> is not set, let's set it to 10% of the sum of
7794 * the possible incoming frontend's maxconns.
7795 */
7796 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
7797 struct proxy *fe;
7798 int total = 0;
7799
7800 /* sum up the number of maxconns of frontends which
7801 * reference this backend at least once or which are
7802 * the same one ('listen').
7803 */
7804 for (fe = proxy; fe; fe = fe->next) {
7805 struct switching_rule *rule;
7806 struct hdr_exp *exp;
7807 int found = 0;
7808
7809 if (!(fe->cap & PR_CAP_FE))
7810 continue;
7811
7812 if (fe == curproxy) /* we're on a "listen" instance */
7813 found = 1;
7814
7815 if (fe->defbe.be == curproxy) /* "default_backend" */
7816 found = 1;
7817
7818 /* check if a "use_backend" rule matches */
7819 if (!found) {
7820 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007821 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02007822 found = 1;
7823 break;
7824 }
7825 }
7826 }
7827
7828 /* check if a "reqsetbe" rule matches */
7829 for (exp = fe->req_exp; !found && exp; exp = exp->next) {
7830 if (exp->action == ACT_SETBE &&
7831 (struct proxy *)exp->replace == curproxy) {
7832 found = 1;
7833 break;
7834 }
7835 }
7836
7837 /* now we've checked all possible ways to reference a backend
7838 * from a frontend.
7839 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02007840 if (!found)
7841 continue;
7842 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02007843 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02007844 /* we have the sum of the maxconns in <total>. We only
7845 * keep 10% of that sum to set the default fullconn, with
7846 * a hard minimum of 1 (to avoid a divide by zero).
7847 */
7848 curproxy->fullconn = (total + 9) / 10;
7849 if (!curproxy->fullconn)
7850 curproxy->fullconn = 1;
7851 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007852 }
7853
Willy Tarreau056f5682010-06-06 15:51:11 +02007854 /* initialize stick-tables on backend capable proxies. This must not
7855 * be done earlier because the data size may be discovered while parsing
7856 * other proxies.
7857 */
Godbach9703e662013-12-11 21:11:41 +08007858 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau58302132014-02-24 20:59:47 +01007859 if (curproxy->state == PR_STSTOPPED)
7860 continue;
7861
Godbach9703e662013-12-11 21:11:41 +08007862 if (!stktable_init(&curproxy->table)) {
7863 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
7864 cfgerr++;
7865 }
7866 }
Willy Tarreau056f5682010-06-06 15:51:11 +02007867
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007868 /*
7869 * Recount currently required checks.
7870 */
7871
7872 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
7873 int optnum;
7874
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007875 for (optnum = 0; cfg_opts[optnum].name; optnum++)
7876 if (curproxy->options & cfg_opts[optnum].val)
7877 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007878
Willy Tarreau66aa61f2009-01-18 21:44:07 +01007879 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
7880 if (curproxy->options2 & cfg_opts2[optnum].val)
7881 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007882 }
7883
Willy Tarreau122541c2011-09-07 21:24:49 +02007884 if (peers) {
7885 struct peers *curpeers = peers, **last;
7886 struct peer *p, *pb;
7887
7888 /* Remove all peers sections which don't have a valid listener.
7889 * This can happen when a peers section is never referenced and
7890 * does not contain a local peer.
7891 */
7892 last = &peers;
7893 while (*last) {
7894 curpeers = *last;
7895 if (curpeers->peers_fe) {
7896 last = &curpeers->next;
7897 continue;
7898 }
7899
7900 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
7901 curpeers->id, localpeer);
7902
7903 p = curpeers->remote;
7904 while (p) {
7905 pb = p->next;
7906 free(p->id);
7907 free(p);
7908 p = pb;
7909 }
7910
7911 /* Destroy and unlink this curpeers section.
7912 * Note: curpeers is backed up into *last.
7913 */
7914 free(curpeers->id);
7915 curpeers = curpeers->next;
7916 free(*last);
7917 *last = curpeers;
7918 }
7919 }
7920
Simon Horman0d16a402015-01-30 11:22:58 +09007921 if (mailers) {
7922 struct mailers *curmailers = mailers, **last;
7923 struct mailer *m, *mb;
7924
7925 /* Remove all mailers sections which don't have a valid listener.
7926 * This can happen when a mailers section is never referenced.
7927 */
7928 last = &mailers;
7929 while (*last) {
7930 curmailers = *last;
7931 if (curmailers->users) {
7932 last = &curmailers->next;
7933 continue;
7934 }
7935
7936 Warning("Removing incomplete section 'mailers %s'.\n",
7937 curmailers->id);
7938
7939 m = curmailers->mailer_list;
7940 while (m) {
7941 mb = m->next;
7942 free(m->id);
7943 free(m);
7944 m = mb;
7945 }
7946
7947 /* Destroy and unlink this curmailers section.
7948 * Note: curmailers is backed up into *last.
7949 */
7950 free(curmailers->id);
7951 curmailers = curmailers->next;
7952 free(*last);
7953 *last = curmailers;
7954 }
7955 }
7956
Willy Tarreau34eb6712011-10-24 18:15:04 +02007957 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02007958 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02007959 MEM_F_SHARED);
7960
Willy Tarreaubb925012009-07-23 13:36:36 +02007961 if (cfgerr > 0)
7962 err_code |= ERR_ALERT | ERR_FATAL;
7963 out:
7964 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007965}
7966
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007967/*
7968 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
7969 * parsing sessions.
7970 */
7971void cfg_register_keywords(struct cfg_kw_list *kwl)
7972{
7973 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
7974}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007975
Willy Tarreau5b2c3362008-07-09 19:39:06 +02007976/*
7977 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
7978 */
7979void cfg_unregister_keywords(struct cfg_kw_list *kwl)
7980{
7981 LIST_DEL(&kwl->list);
7982 LIST_INIT(&kwl->list);
7983}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007984
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007985/* this function register new section in the haproxy configuration file.
7986 * <section_name> is the name of this new section and <section_parser>
7987 * is the called parser. If two section declaration have the same name,
7988 * only the first declared is used.
7989 */
7990int cfg_register_section(char *section_name,
7991 int (*section_parser)(const char *, int, char **, int))
7992{
7993 struct cfg_section *cs;
7994
7995 cs = calloc(1, sizeof(*cs));
7996 if (!cs) {
7997 Alert("register section '%s': out of memory.\n", section_name);
7998 return 0;
7999 }
8000
8001 cs->section_name = section_name;
8002 cs->section_parser = section_parser;
8003
8004 LIST_ADDQ(&sections, &cs->list);
8005
8006 return 1;
8007}
8008
Willy Tarreaubaaee002006-06-26 02:48:02 +02008009/*
8010 * Local variables:
8011 * c-indent-level: 8
8012 * c-basic-offset: 8
8013 * End:
8014 */