blob: 6e2bcd72eb748adca57b2fad286aaa2b0e3063fe [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>
Baptiste Assmann325137d2015-04-13 23:40:55 +020052#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreaueb0c6142007-05-07 00:53:22 +020054#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010055#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020057#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020059#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020060#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020061#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020062#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020063#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010064#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020065#include <proto/lb_fwlc.h>
66#include <proto/lb_fwrr.h>
67#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020072#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010074#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020075#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020076#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020077#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020079#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020080#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Emeric Brunfc0421f2012-09-07 17:30:07 +020084#ifdef USE_OPENSSL
85#include <types/ssl_sock.h>
86#include <proto/ssl_sock.h>
87#include <proto/shctx.h>
88#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020089
Willy Tarreauf3c69202006-07-09 16:42:34 +020090/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
91 * ssl-hello-chk option to ensure that the remote server speaks SSL.
92 *
93 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
94 */
95const char sslv3_client_hello_pkt[] = {
96 "\x16" /* ContentType : 0x16 = Hanshake */
97 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
98 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
99 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
100 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
101 "\x03\x00" /* Hello Version : 0x0300 = v3 */
102 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
103 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
104 "\x00" /* Session ID length : empty (no session ID) */
105 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
106 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
107 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
108 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
109 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
110 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
111 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
112 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
113 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
114 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
115 "\x00\x38" "\x00\x39" "\x00\x3A"
116 "\x01" /* Compression Length : 0x01 = 1 byte for types */
117 "\x00" /* Compression Type : 0x00 = NULL compression */
118};
119
Willy Tarreau3842f002009-06-14 11:39:52 +0200120/* various keyword modifiers */
121enum kw_mod {
122 KWM_STD = 0, /* normal */
123 KWM_NO, /* "no" prefixed before the keyword */
124 KWM_DEF, /* "default" prefixed before the keyword */
125};
126
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100127/* permit to store configuration section */
128struct cfg_section {
129 struct list list;
130 char *section_name;
131 int (*section_parser)(const char *, int, char **, int);
132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141 const char *name;
142 unsigned int val;
143 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100144 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146};
147
148/* proxy->options */
149static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
152 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
153 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
155 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
156 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200158 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200159 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100160 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
162 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
163 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int 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 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &port, &end, err,
242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
243 if (!ss2)
244 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port || !end) {
253 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
254 goto fail;
255 }
256
Emeric Bruned760922010-10-22 17:59:25 +0200257 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
261
262 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100267 else if (ss2->ss_family == AF_UNSPEC) {
268 socklen_t addr_len;
269
270 /* We want to attach to an already bound fd whose number
271 * is in the addr part of ss2 when cast to sockaddr_in.
272 * Note that by definition there is a single listener.
273 * We still have to determine the address family to
274 * register the correct protocol.
275 */
276 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
277 addr_len = sizeof(*ss2);
278 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
279 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
280 goto fail;
281 }
282
283 port = end = get_host_port(ss2);
284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100286 /* OK the address looks correct */
287 ss = *ss2;
288
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 for (; port <= end; port++) {
290 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100291 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200292 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
293 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
294 l->frontend = curproxy;
295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200299 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 l->state = LI_INIT;
301
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100302 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100304 tcpv4_add_listener(l);
305 }
Emeric Bruned760922010-10-22 17:59:25 +0200306 else if (ss.ss_family == AF_INET6) {
307 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
308 tcpv6_add_listener(l);
309 }
310 else {
Emeric Bruned760922010-10-22 17:59:25 +0200311 uxst_add_listener(l);
312 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200313
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200314 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100315 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 } /* end for(port) */
317 } /* end while(next) */
318 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200319 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 fail:
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323}
324
William Lallemand6e62fb62015-04-28 16:55:23 +0200325/*
326 * Report a fatal Alert when there is too much arguments
327 * The index is the current keyword in args
328 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
329 * Fill err_code with an ERR_ALERT and an ERR_FATAL
330 */
331int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
332{
333 char *kw = NULL;
334 int i;
335
336 if (!*args[index + maxarg + 1])
337 return 0;
338
339 memprintf(&kw, "%s", args[0]);
340 for (i = 1; i <= index; i++) {
341 memprintf(&kw, "%s %s", kw, args[i]);
342 }
343
344 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
345 free(kw);
346 *err_code |= ERR_ALERT | ERR_FATAL;
347 return 1;
348}
349
350/*
351 * same as alertif_too_many_args_idx with a 0 index
352 */
353int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
354{
355 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
356}
357
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200358/* Report a warning if a rule is placed after a 'tcp-request content' rule.
359 * Return 1 if the warning has been emitted, otherwise 0.
360 */
361int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
362{
363 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
364 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
365 file, line, arg);
366 return 1;
367 }
368 return 0;
369}
370
Willy Tarreau61d18892009-03-31 10:49:21 +0200371/* Report a warning if a rule is placed after a 'block' rule.
372 * Return 1 if the warning has been emitted, otherwise 0.
373 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100374int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200375{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200376 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200377 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
378 file, line, arg);
379 return 1;
380 }
381 return 0;
382}
383
Willy Tarreau5002f572014-04-23 01:32:02 +0200384/* Report a warning if a rule is placed after an 'http_request' rule.
385 * Return 1 if the warning has been emitted, otherwise 0.
386 */
387int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
388{
389 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
390 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
391 file, line, arg);
392 return 1;
393 }
394 return 0;
395}
396
Willy Tarreau61d18892009-03-31 10:49:21 +0200397/* Report a warning if a rule is placed after a reqrewrite rule.
398 * Return 1 if the warning has been emitted, otherwise 0.
399 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 if (proxy->req_exp) {
403 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
404 file, line, arg);
405 return 1;
406 }
407 return 0;
408}
409
410/* Report a warning if a rule is placed after a reqadd rule.
411 * Return 1 if the warning has been emitted, otherwise 0.
412 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100413int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200414{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100415 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200416 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
417 file, line, arg);
418 return 1;
419 }
420 return 0;
421}
422
423/* Report a warning if a rule is placed after a redirect rule.
424 * Return 1 if the warning has been emitted, otherwise 0.
425 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100426int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200427{
428 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
429 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
430 file, line, arg);
431 return 1;
432 }
433 return 0;
434}
435
436/* Report a warning if a rule is placed after a 'use_backend' rule.
437 * Return 1 if the warning has been emitted, otherwise 0.
438 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100439int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200440{
441 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
442 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
443 file, line, arg);
444 return 1;
445 }
446 return 0;
447}
448
Willy Tarreauee445d92014-04-23 01:39:04 +0200449/* Report a warning if a rule is placed after a 'use-server' rule.
450 * Return 1 if the warning has been emitted, otherwise 0.
451 */
452int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
453{
454 if (!LIST_ISEMPTY(&proxy->server_rules)) {
455 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
456 file, line, arg);
457 return 1;
458 }
459 return 0;
460}
461
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200462/* report a warning if a "tcp request connection" rule is dangerously placed */
463int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
464{
465 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
466 warnif_rule_after_block(proxy, file, line, arg) ||
467 warnif_rule_after_http_req(proxy, file, line, arg) ||
468 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
469 warnif_rule_after_reqadd(proxy, file, line, arg) ||
470 warnif_rule_after_redirect(proxy, file, line, arg) ||
471 warnif_rule_after_use_backend(proxy, file, line, arg) ||
472 warnif_rule_after_use_server(proxy, file, line, arg);
473}
474
475/* report a warning if a "tcp request content" rule is dangerously placed */
476int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
477{
478 return warnif_rule_after_block(proxy, file, line, arg) ||
479 warnif_rule_after_http_req(proxy, file, line, arg) ||
480 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
481 warnif_rule_after_reqadd(proxy, file, line, arg) ||
482 warnif_rule_after_redirect(proxy, file, line, arg) ||
483 warnif_rule_after_use_backend(proxy, file, line, arg) ||
484 warnif_rule_after_use_server(proxy, file, line, arg);
485}
486
Willy Tarreau61d18892009-03-31 10:49:21 +0200487/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100488int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200489{
Willy Tarreau5002f572014-04-23 01:32:02 +0200490 return warnif_rule_after_http_req(proxy, file, line, arg) ||
491 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
492 warnif_rule_after_reqadd(proxy, file, line, arg) ||
493 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200494 warnif_rule_after_use_backend(proxy, file, line, arg) ||
495 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200496}
497
498/* report a warning if an http-request rule is dangerously placed */
499int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
500{
Willy Tarreau61d18892009-03-31 10:49:21 +0200501 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
502 warnif_rule_after_reqadd(proxy, file, line, arg) ||
503 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200504 warnif_rule_after_use_backend(proxy, file, line, arg) ||
505 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200506}
507
508/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100509int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200510{
511 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
512 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200513 warnif_rule_after_use_backend(proxy, file, line, arg) ||
514 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200515}
516
517/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100518int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200519{
520 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200521 warnif_rule_after_use_backend(proxy, file, line, arg) ||
522 warnif_rule_after_use_server(proxy, file, line, arg);
523}
524
525/* report a warning if a redirect rule is dangerously placed */
526int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
527{
528 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
529 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200530}
531
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100532/* Report it if a request ACL condition uses some keywords that are incompatible
533 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
534 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
535 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100536 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100537static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100538{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100539 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200540 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100543 return 0;
544
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100545 acl = acl_cond_conflicts(cond, where);
546 if (acl) {
547 if (acl->name && *acl->name)
548 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
549 file, line, acl->name, sample_ckp_names(where));
550 else
551 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 +0200552 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100553 return ERR_WARN;
554 }
555 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100556 return 0;
557
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100558 if (acl->name && *acl->name)
559 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200560 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 else
562 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200563 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100564 return ERR_WARN;
565}
566
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200568 * parse a line in a <global> section. Returns the error code, 0 if OK, or
569 * any combination of :
570 * - ERR_ABORT: must abort ASAP
571 * - ERR_FATAL: we can continue parsing but not start the service
572 * - ERR_WARN: a warning has been emitted
573 * - ERR_ALERT: an alert has been emitted
574 * Only the two first ones can stop processing, the two others are just
575 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200577int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578{
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200580 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581
582 if (!strcmp(args[0], "global")) { /* new section */
583 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200584 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200587 else if (!strcmp(args[0], "ca-base")) {
588#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200589 if(alertif_too_many_args(1, file, linenum, args, &err_code))
590 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200591 if (global.ca_base != NULL) {
592 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT;
594 goto out;
595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.ca_base = strdup(args[1]);
602#else
603 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
606#endif
607 }
608 else if (!strcmp(args[0], "crt-base")) {
609#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200610 if (alertif_too_many_args(1, file, linenum, args, &err_code))
611 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200612 if (global.crt_base != NULL) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT;
615 goto out;
616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
621 }
622 global.crt_base = strdup(args[1]);
623#else
624 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
625 err_code |= ERR_ALERT | ERR_FATAL;
626 goto out;
627#endif
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200630 if (alertif_too_many_args(0, file, linenum, args, &err_code))
631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 global.mode |= MODE_DAEMON;
633 }
634 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200635 if (alertif_too_many_args(0, file, linenum, args, &err_code))
636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 global.mode |= MODE_DEBUG;
638 }
639 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200640 if (alertif_too_many_args(0, file, linenum, args, &err_code))
641 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100642 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200644 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200645 if (alertif_too_many_args(0, file, linenum, args, &err_code))
646 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100647 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200650 if (alertif_too_many_args(0, file, linenum, args, &err_code))
651 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100652 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100654 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200655 if (alertif_too_many_args(0, file, linenum, args, &err_code))
656 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100657 global.tune.options &= ~GTUNE_USE_SPLICE;
658 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200659 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200660 if (alertif_too_many_args(0, file, linenum, args, &err_code))
661 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200662 global.tune.options &= ~GTUNE_USE_GAI;
663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200665 if (alertif_too_many_args(0, file, linenum, args, &err_code))
666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 global.mode |= MODE_QUIET;
668 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200669 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200670 if (alertif_too_many_args(1, file, linenum, args, &err_code))
671 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 if (global.tune.maxpollevents != 0) {
673 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT;
675 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200676 }
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200681 }
682 global.tune.maxpollevents = atol(args[1]);
683 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100684 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200685 if (alertif_too_many_args(1, file, linenum, args, &err_code))
686 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 if (global.tune.maxaccept != 0) {
688 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200689 err_code |= ERR_ALERT;
690 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100691 }
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100696 }
697 global.tune.maxaccept = atol(args[1]);
698 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200699 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200700 if (alertif_too_many_args(1, file, linenum, args, &err_code))
701 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 if (*(args[1]) == 0) {
703 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 global.tune.chksize = atol(args[1]);
708 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200709#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200710 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200711 if (alertif_too_many_args(0, file, linenum, args, &err_code))
712 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200713 global.tune.sslprivatecache = 1;
714 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100715 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200716 if (alertif_too_many_args(1, file, linenum, args, &err_code))
717 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200718 if (*(args[1]) == 0) {
719 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723 global.tune.sslcachesize = atol(args[1]);
724 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100725 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
726 unsigned int ssllifetime;
727 const char *res;
728
William Lallemand1a748ae2015-05-19 16:37:23 +0200729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
730 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100731 if (*(args[1]) == 0) {
732 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
733 err_code |= ERR_ALERT | ERR_FATAL;
734 goto out;
735 }
736
737 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
738 if (res) {
739 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
740 file, linenum, *res, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744
745 global.tune.ssllifetime = ssllifetime;
746 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100747 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.ssl_max_record = atol(args[1]);
756 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200757#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200758 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
760 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200761 if (*(args[1]) == 0) {
762 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766 global.tune.ssl_default_dh_param = atol(args[1]);
767 if (global.tune.ssl_default_dh_param < 1024) {
768 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200773#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200774 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
776 goto out;
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.ssl_ctx_cache = atoi(args[1]);
783 if (global.tune.ssl_ctx_cache < 0) {
784 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
785 file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200790#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100791 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200792 if (alertif_too_many_args(1, file, linenum, args, &err_code))
793 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.buf_limit = atol(args[1]);
800 if (global.tune.buf_limit) {
801 if (global.tune.buf_limit < 3)
802 global.tune.buf_limit = 3;
803 if (global.tune.buf_limit <= global.tune.reserved_bufs)
804 global.tune.buf_limit = global.tune.reserved_bufs + 1;
805 }
806 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100807 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200808 if (alertif_too_many_args(1, file, linenum, args, &err_code))
809 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100810 if (*(args[1]) == 0) {
811 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815 global.tune.reserved_bufs = atol(args[1]);
816 if (global.tune.reserved_bufs < 2)
817 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100818 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
819 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100820 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200821 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200824 if (*(args[1]) == 0) {
825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT | ERR_FATAL;
827 goto out;
828 }
829 global.tune.bufsize = atol(args[1]);
830 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
831 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100832 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100833 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200834 }
835 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200838 if (*(args[1]) == 0) {
839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 global.tune.maxrewrite = atol(args[1]);
844 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
845 global.tune.maxrewrite = global.tune.bufsize / 2;
846 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100847 else if (!strcmp(args[0], "tune.idletimer")) {
848 unsigned int idle;
849 const char *res;
850
William Lallemand1a748ae2015-05-19 16:37:23 +0200851 if (alertif_too_many_args(1, file, linenum, args, &err_code))
852 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100853 if (*(args[1]) == 0) {
854 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858
859 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
860 if (res) {
861 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
862 file, linenum, *res, args[0]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866
867 if (idle > 65535) {
868 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872 global.tune.idle_timer = idle;
873 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100874 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200875 if (alertif_too_many_args(1, file, linenum, args, &err_code))
876 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100877 if (global.tune.client_rcvbuf != 0) {
878 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT;
880 goto out;
881 }
882 if (*(args[1]) == 0) {
883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
884 err_code |= ERR_ALERT | ERR_FATAL;
885 goto out;
886 }
887 global.tune.client_rcvbuf = atol(args[1]);
888 }
889 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200890 if (alertif_too_many_args(1, file, linenum, args, &err_code))
891 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100892 if (global.tune.server_rcvbuf != 0) {
893 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT;
895 goto out;
896 }
897 if (*(args[1]) == 0) {
898 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 global.tune.server_rcvbuf = atol(args[1]);
903 }
904 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200905 if (alertif_too_many_args(1, file, linenum, args, &err_code))
906 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100907 if (global.tune.client_sndbuf != 0) {
908 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
909 err_code |= ERR_ALERT;
910 goto out;
911 }
912 if (*(args[1]) == 0) {
913 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917 global.tune.client_sndbuf = atol(args[1]);
918 }
919 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200920 if (alertif_too_many_args(1, file, linenum, args, &err_code))
921 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100922 if (global.tune.server_sndbuf != 0) {
923 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
924 err_code |= ERR_ALERT;
925 goto out;
926 }
927 if (*(args[1]) == 0) {
928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
931 }
932 global.tune.server_sndbuf = atol(args[1]);
933 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200934 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200935 if (alertif_too_many_args(1, file, linenum, args, &err_code))
936 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200937 if (*(args[1]) == 0) {
938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942 global.tune.pipesize = atol(args[1]);
943 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100944 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200945 if (alertif_too_many_args(1, file, linenum, args, &err_code))
946 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 global.tune.cookie_len = atol(args[1]) + 1;
953 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200954 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200955 if (alertif_too_many_args(1, file, linenum, args, &err_code))
956 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200957 if (*(args[1]) == 0) {
958 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto out;
961 }
962 global.tune.max_http_hdr = atol(args[1]);
963 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100964 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
965#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200966 if (alertif_too_many_args(1, file, linenum, args, &err_code))
967 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100968 if (*args[1]) {
969 global.tune.zlibmemlevel = atoi(args[1]);
970 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
971 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
972 file, linenum, args[0]);
973 err_code |= ERR_ALERT | ERR_FATAL;
974 goto out;
975 }
976 } else {
977 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
978 file, linenum, args[0]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981 }
982#else
983 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986#endif
987 }
988 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
989#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200990 if (alertif_too_many_args(1, file, linenum, args, &err_code))
991 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100992 if (*args[1]) {
993 global.tune.zlibwindowsize = atoi(args[1]);
994 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
995 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
996 file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 } else {
1001 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1002 file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006#else
1007 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010#endif
1011 }
William Lallemandf3747832012-11-09 12:33:10 +01001012 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001013 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1014 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001015 if (*args[1]) {
1016 global.tune.comp_maxlevel = atoi(args[1]);
1017 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1018 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1019 file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023 } else {
1024 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1025 file, linenum, args[0]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001030 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1031 if (*args[1]) {
1032 global.tune.pattern_cache = atoi(args[1]);
1033 if (global.tune.pattern_cache < 0) {
1034 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1035 file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 } else {
1040 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1041 file, linenum, args[0]);
1042 err_code |= ERR_ALERT | ERR_FATAL;
1043 goto out;
1044 }
1045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001047 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001050 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT;
1052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 }
1054 if (*(args[1]) == 0) {
1055 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
1057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 global.uid = atol(args[1]);
1060 }
1061 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001065 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074 global.gid = atol(args[1]);
1075 }
Simon Horman98637e52014-06-20 12:30:16 +09001076 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001077 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1078 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001079 global.external_check = 1;
1080 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001081 /* user/group name handling */
1082 else if (!strcmp(args[0], "user")) {
1083 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001086 if (global.uid != 0) {
1087 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT;
1089 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001090 }
1091 errno = 0;
1092 ha_user = getpwnam(args[1]);
1093 if (ha_user != NULL) {
1094 global.uid = (int)ha_user->pw_uid;
1095 }
1096 else {
1097 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 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001099 }
1100 }
1101 else if (!strcmp(args[0], "group")) {
1102 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001105 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001106 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT;
1108 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 }
1110 errno = 0;
1111 ha_group = getgrnam(args[1]);
1112 if (ha_group != NULL) {
1113 global.gid = (int)ha_group->gr_gid;
1114 }
1115 else {
1116 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 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 }
1120 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001122 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001130 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1131 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1132 file, linenum, args[0], LONGBITS, global.nbproc);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
1135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
1137 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001138 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 if (global.maxconn != 0) {
1141 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001142 err_code |= ERR_ALERT;
1143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 }
1145 if (*(args[1]) == 0) {
1146 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT | ERR_FATAL;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
1150 global.maxconn = atol(args[1]);
1151#ifdef SYSTEM_MAXCONN
1152 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1153 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);
1154 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001155 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157#endif /* SYSTEM_MAXCONN */
1158 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001159 else if (!strcmp(args[0], "maxsslconn")) {
1160#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001161 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1162 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001163 if (*(args[1]) == 0) {
1164 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168 global.maxsslconn = atol(args[1]);
1169#else
Emeric Brun0914df82012-10-02 18:45:42 +02001170 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001173#endif
1174 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001175 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1176#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001177 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1178 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001179 if (*(args[1]) == 0) {
1180 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
1183 }
1184 free(global.listen_default_ciphers);
1185 global.listen_default_ciphers = strdup(args[1]);
1186#else
1187 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190#endif
1191 }
1192 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1193#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001194 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1195 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001196 if (*(args[1]) == 0) {
1197 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1198 err_code |= ERR_ALERT | ERR_FATAL;
1199 goto out;
1200 }
1201 free(global.connect_default_ciphers);
1202 global.connect_default_ciphers = strdup(args[1]);
1203#else
1204 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207#endif
1208 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001209#ifdef USE_OPENSSL
1210#ifndef OPENSSL_NO_DH
1211 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1212 if (*(args[1]) == 0) {
1213 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
1216 }
1217 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1218 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222 }
1223#endif
1224#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001225 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001226 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1227 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001228 if (*(args[1]) == 0) {
1229 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
1232 }
1233 if (strcmp(args[1],"none") == 0)
1234 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1235 else if (strcmp(args[1],"required") == 0)
1236 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1237 else {
1238 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1239 err_code |= ERR_ALERT | ERR_FATAL;
1240 goto out;
1241 }
1242 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001243 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001244 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1245 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001246 if (global.cps_lim != 0) {
1247 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1248 err_code |= ERR_ALERT;
1249 goto out;
1250 }
1251 if (*(args[1]) == 0) {
1252 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1253 err_code |= ERR_ALERT | ERR_FATAL;
1254 goto out;
1255 }
1256 global.cps_lim = atol(args[1]);
1257 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001258 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001259 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1260 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001261 if (global.sps_lim != 0) {
1262 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1263 err_code |= ERR_ALERT;
1264 goto out;
1265 }
1266 if (*(args[1]) == 0) {
1267 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271 global.sps_lim = atol(args[1]);
1272 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001273 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001274 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1275 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001276 if (global.ssl_lim != 0) {
1277 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1278 err_code |= ERR_ALERT;
1279 goto out;
1280 }
1281 if (*(args[1]) == 0) {
1282 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
1285 }
1286 global.ssl_lim = atol(args[1]);
1287 }
William Lallemandd85f9172012-11-09 17:05:39 +01001288 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001289 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1290 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001291 if (*(args[1]) == 0) {
1292 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
1296 global.comp_rate_lim = atoi(args[1]) * 1024;
1297 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001298 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001299 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1300 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001301 if (global.maxpipes != 0) {
1302 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 err_code |= ERR_ALERT;
1304 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001305 }
1306 if (*(args[1]) == 0) {
1307 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001310 }
1311 global.maxpipes = atol(args[1]);
1312 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001313 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001314 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1315 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001316 if (*(args[1]) == 0) {
1317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
1320 }
William Lallemande3a7d992012-11-20 11:25:20 +01001321 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001322 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001323 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001324 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1325 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001326 if (*(args[1]) == 0) {
1327 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001332 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001333 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
1336 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001337 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001338
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001340 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 if (global.rlimit_nofile != 0) {
1343 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001344 err_code |= ERR_ALERT;
1345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 }
1347 if (*(args[1]) == 0) {
1348 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001349 err_code |= ERR_ALERT | ERR_FATAL;
1350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 }
1352 global.rlimit_nofile = atol(args[1]);
1353 }
1354 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001355 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 if (global.chroot != NULL) {
1358 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001359 err_code |= ERR_ALERT;
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 }
1362 if (*(args[1]) == 0) {
1363 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 }
1367 global.chroot = strdup(args[1]);
1368 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001369 else if (!strcmp(args[0], "description")) {
1370 int i, len=0;
1371 char *d;
1372
1373 if (!*args[1]) {
1374 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1375 file, linenum, args[0]);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
1378 }
1379
Willy Tarreau348acfe2014-04-14 15:00:39 +02001380 for (i = 1; *args[i]; i++)
1381 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001382
1383 if (global.desc)
1384 free(global.desc);
1385
1386 global.desc = d = (char *)calloc(1, len);
1387
Willy Tarreau348acfe2014-04-14 15:00:39 +02001388 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1389 for (i = 2; *args[i]; i++)
1390 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001391 }
1392 else if (!strcmp(args[0], "node")) {
1393 int i;
1394 char c;
1395
William Lallemand1a748ae2015-05-19 16:37:23 +02001396 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1397 goto out;
1398
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001399 for (i=0; args[1][i]; i++) {
1400 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001401 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1402 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001403 break;
1404 }
1405
1406 if (!i || args[1][i]) {
1407 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1408 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1409 file, linenum, args[0]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
1412 }
1413
1414 if (global.node)
1415 free(global.node);
1416
1417 global.node = strdup(args[1]);
1418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001420 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 if (global.pidfile != NULL) {
1423 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001424 err_code |= ERR_ALERT;
1425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 }
1427 if (*(args[1]) == 0) {
1428 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 }
1432 global.pidfile = strdup(args[1]);
1433 }
Emeric Bruned760922010-10-22 17:59:25 +02001434 else if (!strcmp(args[0], "unix-bind")) {
1435 int cur_arg = 1;
1436 while (*(args[cur_arg])) {
1437 if (!strcmp(args[cur_arg], "prefix")) {
1438 if (global.unix_bind.prefix != NULL) {
1439 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1440 err_code |= ERR_ALERT;
1441 cur_arg += 2;
1442 continue;
1443 }
1444
1445 if (*(args[cur_arg+1]) == 0) {
1446 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1447 err_code |= ERR_ALERT | ERR_FATAL;
1448 goto out;
1449 }
1450 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1451 cur_arg += 2;
1452 continue;
1453 }
1454
1455 if (!strcmp(args[cur_arg], "mode")) {
1456
1457 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1458 cur_arg += 2;
1459 continue;
1460 }
1461
1462 if (!strcmp(args[cur_arg], "uid")) {
1463
1464 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1465 cur_arg += 2;
1466 continue;
1467 }
1468
1469 if (!strcmp(args[cur_arg], "gid")) {
1470
1471 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1472 cur_arg += 2;
1473 continue;
1474 }
1475
1476 if (!strcmp(args[cur_arg], "user")) {
1477 struct passwd *user;
1478
1479 user = getpwnam(args[cur_arg + 1]);
1480 if (!user) {
1481 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1482 file, linenum, args[0], args[cur_arg + 1 ]);
1483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
1485 }
1486
1487 global.unix_bind.ux.uid = user->pw_uid;
1488 cur_arg += 2;
1489 continue;
1490 }
1491
1492 if (!strcmp(args[cur_arg], "group")) {
1493 struct group *group;
1494
1495 group = getgrnam(args[cur_arg + 1]);
1496 if (!group) {
1497 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1498 file, linenum, args[0], args[cur_arg + 1 ]);
1499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
1501 }
1502
1503 global.unix_bind.ux.gid = group->gr_gid;
1504 cur_arg += 2;
1505 continue;
1506 }
1507
Willy Tarreaub48f9582011-09-05 01:17:06 +02001508 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001509 file, linenum, args[0]);
1510 err_code |= ERR_ALERT | ERR_FATAL;
1511 goto out;
1512 }
1513 }
William Lallemand0f99e342011-10-12 17:50:54 +02001514 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1515 /* delete previous herited or defined syslog servers */
1516 struct logsrv *back;
1517 struct logsrv *tmp;
1518
1519 if (*(args[1]) != 0) {
1520 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto out;
1523 }
1524
1525 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1526 LIST_DEL(&tmp->list);
1527 free(tmp);
1528 }
1529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001531 struct sockaddr_storage *sk;
1532 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001533 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001534 int arg = 0;
1535 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001536
William Lallemand1a748ae2015-05-19 16:37:23 +02001537 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1538 goto out;
1539
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 if (*(args[1]) == 0 || *(args[2]) == 0) {
1541 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001542 err_code |= ERR_ALERT | ERR_FATAL;
1543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 }
William Lallemand0f99e342011-10-12 17:50:54 +02001545
1546 logsrv = calloc(1, sizeof(struct logsrv));
1547
Willy Tarreau18324f52014-06-27 18:10:07 +02001548 /* just after the address, a length may be specified */
1549 if (strcmp(args[arg+2], "len") == 0) {
1550 len = atoi(args[arg+3]);
1551 if (len < 80 || len > 65535) {
1552 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1553 file, linenum, args[arg+3]);
1554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
1557 logsrv->maxlen = len;
1558
1559 /* skip these two args */
1560 arg += 2;
1561 }
1562 else
1563 logsrv->maxlen = MAX_SYSLOG_LEN;
1564
1565 if (logsrv->maxlen > global.max_syslog_len) {
1566 global.max_syslog_len = logsrv->maxlen;
1567 logline = realloc(logline, global.max_syslog_len + 1);
1568 }
1569
William Lallemand1a748ae2015-05-19 16:37:23 +02001570 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1571 goto out;
1572
Willy Tarreau18324f52014-06-27 18:10:07 +02001573 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001574 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001575 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001577 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
1579
William Lallemand0f99e342011-10-12 17:50:54 +02001580 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001581 if (*(args[arg+3])) {
1582 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001583 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001584 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001586 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
1588 }
1589
William Lallemand0f99e342011-10-12 17:50:54 +02001590 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001591 if (*(args[arg+4])) {
1592 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001593 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001594 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001596 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001597 }
1598 }
1599
Willy Tarreau902636f2013-03-10 19:44:48 +01001600 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001601 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001602 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001603 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001604 free(logsrv);
1605 goto out;
1606 }
1607 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001608
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001609 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001610 if (port1 != port2) {
1611 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1612 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001613 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001614 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001615 goto out;
1616 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001617
William Lallemand0f99e342011-10-12 17:50:54 +02001618 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001619 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001620 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622
William Lallemand0f99e342011-10-12 17:50:54 +02001623 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001624 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001625 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1626 char *name;
1627 int len;
1628
1629 if (global.log_send_hostname != NULL) {
1630 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1631 err_code |= ERR_ALERT;
1632 goto out;
1633 }
1634
1635 if (*(args[1]))
1636 name = args[1];
1637 else
1638 name = hostname;
1639
1640 len = strlen(name);
1641
1642 /* We'll add a space after the name to respect the log format */
1643 free(global.log_send_hostname);
1644 global.log_send_hostname = malloc(len + 2);
1645 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1646 }
Kevinm48936af2010-12-22 16:08:21 +00001647 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001648 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1649 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001650 if (*(args[1]) == 0) {
1651 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
1654 }
1655 free(global.log_tag);
1656 global.log_tag = strdup(args[1]);
1657 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001658 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001659 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1660 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001661 if (global.spread_checks != 0) {
1662 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001663 err_code |= ERR_ALERT;
1664 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001665 }
1666 if (*(args[1]) == 0) {
1667 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001670 }
1671 global.spread_checks = atol(args[1]);
1672 if (global.spread_checks < 0 || global.spread_checks > 50) {
1673 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001677 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1678 const char *err;
1679 unsigned int val;
1680
William Lallemand1a748ae2015-05-19 16:37:23 +02001681 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1682 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001683 if (*(args[1]) == 0) {
1684 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
1687 }
1688
1689 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1690 if (err) {
1691 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1692 err_code |= ERR_ALERT | ERR_FATAL;
1693 }
1694 global.max_spread_checks = val;
1695 if (global.max_spread_checks < 0) {
1696 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1697 err_code |= ERR_ALERT | ERR_FATAL;
1698 }
1699 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001700 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1701#ifdef USE_CPU_AFFINITY
1702 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001703 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001704 unsigned long cpus = 0;
1705
1706 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001707 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001708 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001709 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001710 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001711 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001712 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001713 proc = atol(args[1]);
1714 if (proc >= 1 && proc <= LONGBITS)
1715 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001716 }
1717
1718 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001719 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",
1720 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
1724
1725 cur_arg = 2;
1726 while (*args[cur_arg]) {
1727 unsigned int low, high;
1728
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001729 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001730 char *dash = strchr(args[cur_arg], '-');
1731
1732 low = high = str2uic(args[cur_arg]);
1733 if (dash)
1734 high = str2uic(dash + 1);
1735
1736 if (high < low) {
1737 unsigned int swap = low;
1738 low = high;
1739 high = swap;
1740 }
1741
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001742 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001743 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001744 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748
1749 while (low <= high)
1750 cpus |= 1UL << low++;
1751 }
1752 else {
1753 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1754 file, linenum, args[0], args[cur_arg]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758 cur_arg++;
1759 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001760 for (i = 0; i < LONGBITS; i++)
1761 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001762 global.cpu_map[i] = cpus;
1763#else
1764 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767#endif
1768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001770 struct cfg_kw_list *kwl;
1771 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001772 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001773
1774 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1775 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1776 if (kwl->kw[index].section != CFG_GLOBAL)
1777 continue;
1778 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001779 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001780 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001781 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001782 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001783 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001784 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001785 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001786 err_code |= ERR_WARN;
1787 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001788 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001789 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001790 }
1791 }
1792 }
1793
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001795 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001797
Willy Tarreau058e9072009-07-20 09:30:05 +02001798 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001799 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001800 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801}
1802
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001803void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001805 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 defproxy.mode = PR_MODE_TCP;
1807 defproxy.state = PR_STNEW;
1808 defproxy.maxconn = cfg_maxpconn;
1809 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001810 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001811
Simon Horman66183002013-02-23 10:16:43 +09001812 defproxy.defsrv.check.inter = DEF_CHKINTR;
1813 defproxy.defsrv.check.fastinter = 0;
1814 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001815 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1816 defproxy.defsrv.agent.fastinter = 0;
1817 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001818 defproxy.defsrv.check.rise = DEF_RISETIME;
1819 defproxy.defsrv.check.fall = DEF_FALLTIME;
1820 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1821 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001822 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001823 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001824 defproxy.defsrv.maxqueue = 0;
1825 defproxy.defsrv.minconn = 0;
1826 defproxy.defsrv.maxconn = 0;
1827 defproxy.defsrv.slowstart = 0;
1828 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1829 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1830 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001831
1832 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833}
1834
Willy Tarreauade5ec42010-01-28 19:33:49 +01001835
Willy Tarreau63af98d2014-05-18 08:11:41 +02001836/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1837 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1838 * ERR_FATAL in case of error.
1839 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001840static int create_cond_regex_rule(const char *file, int line,
1841 struct proxy *px, int dir, int action, int flags,
1842 const char *cmd, const char *reg, const char *repl,
1843 const char **cond_start)
1844{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001845 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001846 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001847 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001848 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001849 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001850 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001851 int cs;
1852 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001853
1854 if (px == &defproxy) {
1855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001856 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001857 goto err;
1858 }
1859
1860 if (*reg == 0) {
1861 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001862 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001863 goto err;
1864 }
1865
1866 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001867 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001868
Willy Tarreau5321c422010-01-28 20:35:13 +01001869 if (cond_start &&
1870 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001871 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1872 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1873 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001874 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001875 goto err;
1876 }
1877 }
1878 else if (cond_start && **cond_start) {
1879 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1880 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001881 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001882 goto err;
1883 }
1884
Willy Tarreau63af98d2014-05-18 08:11:41 +02001885 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001886 (dir == SMP_OPT_DIR_REQ) ?
1887 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1888 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1889 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001890
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001891 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001892 if (!preg) {
1893 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001895 goto err;
1896 }
1897
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001898 cs = !(flags & REG_ICASE);
1899 cap = !(flags & REG_NOSUB);
1900 error = NULL;
1901 if (!regex_comp(reg, preg, cs, cap, &error)) {
1902 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1903 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001904 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001905 goto err;
1906 }
1907
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001908 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001909 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001910 if (repl && err) {
1911 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1912 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001913 ret_code |= ERR_ALERT | ERR_FATAL;
1914 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001915 }
1916
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001917 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001918 ret_code |= ERR_WARN;
1919
1920 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001921
Willy Tarreau63af98d2014-05-18 08:11:41 +02001922 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001923 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001924 err:
1925 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001926 free(errmsg);
1927 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001928}
1929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930/*
William Lallemand51097192015-04-14 16:35:22 +02001931 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001932 * Returns the error code, 0 if OK, or any combination of :
1933 * - ERR_ABORT: must abort ASAP
1934 * - ERR_FATAL: we can continue parsing but not start the service
1935 * - ERR_WARN: a warning has been emitted
1936 * - ERR_ALERT: an alert has been emitted
1937 * Only the two first ones can stop processing, the two others are just
1938 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001940int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1941{
1942 static struct peers *curpeers = NULL;
1943 struct peer *newpeer = NULL;
1944 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001945 struct bind_conf *bind_conf;
1946 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001947 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001948 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001949
1950 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001951 if (!*args[1]) {
1952 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001953 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001954 goto out;
1955 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001956
William Lallemand6e62fb62015-04-28 16:55:23 +02001957 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1958 goto out;
1959
Emeric Brun32da3c42010-09-23 18:39:19 +02001960 err = invalid_char(args[1]);
1961 if (err) {
1962 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1963 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001964 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001965 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001966 }
1967
1968 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1969 /*
1970 * If there are two proxies with the same name only following
1971 * combinations are allowed:
1972 */
1973 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001974 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001975 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001976 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001977 }
1978 }
1979
1980 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1981 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1982 err_code |= ERR_ALERT | ERR_ABORT;
1983 goto out;
1984 }
1985
1986 curpeers->next = peers;
1987 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001988 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001989 curpeers->conf.line = linenum;
1990 curpeers->last_change = now.tv_sec;
1991 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001992 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001993 }
1994 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001995 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001996 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001997 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001998
1999 if (!*args[2]) {
2000 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2001 file, linenum, args[0]);
2002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
2004 }
2005
2006 err = invalid_char(args[1]);
2007 if (err) {
2008 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2009 file, linenum, *err, args[1]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
2013
2014 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2015 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2016 err_code |= ERR_ALERT | ERR_ABORT;
2017 goto out;
2018 }
2019
2020 /* the peers are linked backwards first */
2021 curpeers->count++;
2022 newpeer->next = curpeers->remote;
2023 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002024 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002025 newpeer->conf.line = linenum;
2026
2027 newpeer->last_change = now.tv_sec;
2028 newpeer->id = strdup(args[1]);
2029
Willy Tarreau902636f2013-03-10 19:44:48 +01002030 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002031 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002032 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002033 err_code |= ERR_ALERT | ERR_FATAL;
2034 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002036
2037 proto = protocol_by_family(sk->ss_family);
2038 if (!proto || !proto->connect) {
2039 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2040 file, linenum, args[0], args[1]);
2041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
2043 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002044
2045 if (port1 != port2) {
2046 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2047 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
2050 }
2051
Willy Tarreau2aa38802013-02-20 19:20:59 +01002052 if (!port1) {
2053 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2054 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002058
Emeric Brun32da3c42010-09-23 18:39:19 +02002059 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002060 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002061 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002062 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002063
Emeric Brun32da3c42010-09-23 18:39:19 +02002064 if (strcmp(newpeer->id, localpeer) == 0) {
2065 /* Current is local peer, it define a frontend */
2066 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002067 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002068
2069 if (!curpeers->peers_fe) {
2070 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2072 err_code |= ERR_ALERT | ERR_ABORT;
2073 goto out;
2074 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002075
Willy Tarreau237250c2011-07-29 01:49:03 +02002076 init_new_proxy(curpeers->peers_fe);
2077 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002078 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002079 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2080 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002081 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002082
2083 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2084
Willy Tarreau902636f2013-03-10 19:44:48 +01002085 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2086 if (errmsg && *errmsg) {
2087 indent_msg(&errmsg, 2);
2088 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002089 }
2090 else
2091 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2092 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002093 err_code |= ERR_FATAL;
2094 goto out;
2095 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002096
2097 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002098 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002099 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2100 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002101 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002102 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002103 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002104 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002105 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2106 global.maxsock += l->maxconn;
2107 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002109 else {
2110 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2111 file, linenum, args[0], args[1],
2112 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2113 err_code |= ERR_FATAL;
2114 goto out;
2115 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002116 }
2117 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002118 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2119 curpeers->state = PR_STSTOPPED;
2120 }
2121 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2122 curpeers->state = PR_STNEW;
2123 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002124 else if (*args[0] != 0) {
2125 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
2128 }
2129
2130out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002131 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002132 return err_code;
2133}
2134
Baptiste Assmann325137d2015-04-13 23:40:55 +02002135/*
2136 * Parse a <resolvers> section.
2137 * Returns the error code, 0 if OK, or any combination of :
2138 * - ERR_ABORT: must abort ASAP
2139 * - ERR_FATAL: we can continue parsing but not start the service
2140 * - ERR_WARN: a warning has been emitted
2141 * - ERR_ALERT: an alert has been emitted
2142 * Only the two first ones can stop processing, the two others are just
2143 * indicators.
2144 */
2145int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2146{
2147 static struct dns_resolvers *curr_resolvers = NULL;
2148 struct dns_nameserver *newnameserver = NULL;
2149 const char *err;
2150 int err_code = 0;
2151 char *errmsg = NULL;
2152
2153 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2154 if (!*args[1]) {
2155 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2156 err_code |= ERR_ALERT | ERR_ABORT;
2157 goto out;
2158 }
2159
2160 err = invalid_char(args[1]);
2161 if (err) {
2162 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2163 file, linenum, *err, args[0], args[1]);
2164 err_code |= ERR_ALERT | ERR_ABORT;
2165 goto out;
2166 }
2167
2168 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2169 /* Error if two resolvers owns the same name */
2170 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2171 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2172 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2173 err_code |= ERR_ALERT | ERR_ABORT;
2174 }
2175 }
2176
2177 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2178 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2179 err_code |= ERR_ALERT | ERR_ABORT;
2180 goto out;
2181 }
2182
2183 /* default values */
2184 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2185 curr_resolvers->conf.file = strdup(file);
2186 curr_resolvers->conf.line = linenum;
2187 curr_resolvers->id = strdup(args[1]);
2188 curr_resolvers->query_ids = EB_ROOT;
2189 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002190 curr_resolvers->hold.valid = 10000;
2191 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002192 curr_resolvers->resolve_retries = 3;
2193 LIST_INIT(&curr_resolvers->nameserver_list);
2194 LIST_INIT(&curr_resolvers->curr_resolution);
2195 }
2196 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2197 struct sockaddr_storage *sk;
2198 int port1, port2;
2199 struct protocol *proto;
2200
2201 if (!*args[2]) {
2202 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2203 file, linenum, args[0]);
2204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
2206 }
2207
2208 err = invalid_char(args[1]);
2209 if (err) {
2210 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2211 file, linenum, *err, args[1]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
2215
2216 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2218 err_code |= ERR_ALERT | ERR_ABORT;
2219 goto out;
2220 }
2221
2222 /* the nameservers are linked backward first */
2223 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2224 curr_resolvers->count_nameservers++;
2225 newnameserver->resolvers = curr_resolvers;
2226 newnameserver->conf.file = strdup(file);
2227 newnameserver->conf.line = linenum;
2228 newnameserver->id = strdup(args[1]);
2229
2230 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2231 if (!sk) {
2232 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236
2237 proto = protocol_by_family(sk->ss_family);
2238 if (!proto || !proto->connect) {
2239 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2240 file, linenum, args[0], args[1]);
2241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
2243 }
2244
2245 if (port1 != port2) {
2246 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2247 file, linenum, args[0], args[1], args[2]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251
2252 newnameserver->addr = *sk;
2253 }
2254 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2255 const char *res;
2256 unsigned int time;
2257
2258 if (!*args[2]) {
2259 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2260 file, linenum, args[0]);
2261 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
2264 }
2265 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2266 if (res) {
2267 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2268 file, linenum, *res, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272 if (strcmp(args[1], "valid") == 0)
2273 curr_resolvers->hold.valid = time;
2274 else {
2275 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2276 file, linenum, args[0], args[1]);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280
2281 }
2282 else if (strcmp(args[0], "resolve_retries") == 0) {
2283 if (!*args[1]) {
2284 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2285 file, linenum, args[0]);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289 curr_resolvers->resolve_retries = atoi(args[1]);
2290 }
2291 else if (strcmp(args[0], "timeout") == 0) {
2292 const char *res;
2293 unsigned int timeout_retry;
2294
2295 if (!*args[2]) {
2296 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2297 file, linenum, args[0]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2302 if (res) {
2303 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2304 file, linenum, *res, args[0]);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308 curr_resolvers->timeout.retry = timeout_retry;
2309 } /* neither "nameserver" nor "resolvers" */
2310 else if (*args[0] != 0) {
2311 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
2314 }
2315
2316 out:
2317 free(errmsg);
2318 return err_code;
2319}
Simon Horman0d16a402015-01-30 11:22:58 +09002320
2321/*
William Lallemand51097192015-04-14 16:35:22 +02002322 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002323 * Returns the error code, 0 if OK, or any combination of :
2324 * - ERR_ABORT: must abort ASAP
2325 * - ERR_FATAL: we can continue parsing but not start the service
2326 * - ERR_WARN: a warning has been emitted
2327 * - ERR_ALERT: an alert has been emitted
2328 * Only the two first ones can stop processing, the two others are just
2329 * indicators.
2330 */
2331int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2332{
2333 static struct mailers *curmailers = NULL;
2334 struct mailer *newmailer = NULL;
2335 const char *err;
2336 int err_code = 0;
2337 char *errmsg = NULL;
2338
2339 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2340 if (!*args[1]) {
2341 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2342 err_code |= ERR_ALERT | ERR_ABORT;
2343 goto out;
2344 }
2345
2346 err = invalid_char(args[1]);
2347 if (err) {
2348 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2349 file, linenum, *err, args[0], args[1]);
2350 err_code |= ERR_ALERT | ERR_ABORT;
2351 goto out;
2352 }
2353
2354 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2355 /*
2356 * If there are two proxies with the same name only following
2357 * combinations are allowed:
2358 */
2359 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002360 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002361 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002363 }
2364 }
2365
2366 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2367 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2368 err_code |= ERR_ALERT | ERR_ABORT;
2369 goto out;
2370 }
2371
2372 curmailers->next = mailers;
2373 mailers = curmailers;
2374 curmailers->conf.file = strdup(file);
2375 curmailers->conf.line = linenum;
2376 curmailers->id = strdup(args[1]);
2377 }
2378 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2379 struct sockaddr_storage *sk;
2380 int port1, port2;
2381 struct protocol *proto;
2382
2383 if (!*args[2]) {
2384 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2385 file, linenum, args[0]);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
2389
2390 err = invalid_char(args[1]);
2391 if (err) {
2392 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2393 file, linenum, *err, args[1]);
2394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
2396 }
2397
2398 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 /* the mailers are linked backwards first */
2405 curmailers->count++;
2406 newmailer->next = curmailers->mailer_list;
2407 curmailers->mailer_list = newmailer;
2408 newmailer->mailers = curmailers;
2409 newmailer->conf.file = strdup(file);
2410 newmailer->conf.line = linenum;
2411
2412 newmailer->id = strdup(args[1]);
2413
2414 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2415 if (!sk) {
2416 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
2419 }
2420
2421 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002422 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2423 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002424 file, linenum, args[0], args[1]);
2425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
2427 }
2428
2429 if (port1 != port2) {
2430 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2431 file, linenum, args[0], args[1], args[2]);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435
2436 if (!port1) {
2437 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2438 file, linenum, args[0], args[1], args[2]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442
2443 newmailer->addr = *sk;
2444 newmailer->proto = proto;
2445 newmailer->xprt = &raw_sock;
2446 newmailer->sock_init_arg = NULL;
2447 } /* neither "mailer" nor "mailers" */
2448 else if (*args[0] != 0) {
2449 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
2452 }
2453
2454out:
2455 free(errmsg);
2456 return err_code;
2457}
2458
Simon Horman9dc49962015-01-30 11:22:59 +09002459static void free_email_alert(struct proxy *p)
2460{
2461 free(p->email_alert.mailers.name);
2462 p->email_alert.mailers.name = NULL;
2463 free(p->email_alert.from);
2464 p->email_alert.from = NULL;
2465 free(p->email_alert.to);
2466 p->email_alert.to = NULL;
2467 free(p->email_alert.myhostname);
2468 p->email_alert.myhostname = NULL;
2469}
2470
Willy Tarreau3842f002009-06-14 11:39:52 +02002471int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472{
2473 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002474 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002475 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002476 int rc;
2477 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002478 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002479 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002480 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002481 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002482 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483
Willy Tarreau977b8e42006-12-29 14:19:17 +01002484 if (!strcmp(args[0], "listen"))
2485 rc = PR_CAP_LISTEN;
2486 else if (!strcmp(args[0], "frontend"))
2487 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002488 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002490 else
2491 rc = PR_CAP_NONE;
2492
2493 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 if (!*args[1]) {
2495 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2496 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_ABORT;
2499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002501
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002502 err = invalid_char(args[1]);
2503 if (err) {
2504 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2505 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002507 }
2508
Willy Tarreau8f50b682015-05-26 11:45:02 +02002509 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2510 if (curproxy) {
2511 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2512 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2513 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002515 }
2516
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2518 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_ABORT;
2520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002522
Willy Tarreau97cb7802010-01-03 20:23:58 +01002523 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 curproxy->next = proxy;
2525 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002526 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2527 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002528 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002531 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532
William Lallemand6e62fb62015-04-28 16:55:23 +02002533 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2534 if (curproxy->cap & PR_CAP_FE)
2535 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 }
2538
2539 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002540 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002541 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002542
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002545 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002546 curproxy->no_options = defproxy.no_options;
2547 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002548 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002549 curproxy->except_net = defproxy.except_net;
2550 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002551 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002552 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002554 if (defproxy.fwdfor_hdr_len) {
2555 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2556 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2557 }
2558
Willy Tarreaub86db342009-11-30 11:50:16 +01002559 if (defproxy.orgto_hdr_len) {
2560 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2561 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2562 }
2563
Mark Lamourinec2247f02012-01-04 13:02:01 -05002564 if (defproxy.server_id_hdr_len) {
2565 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2566 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2567 }
2568
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (curproxy->cap & PR_CAP_FE) {
2570 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002571 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002572 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002573
2574 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002575 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2576 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577
2578 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002582 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 curproxy->fullconn = defproxy.fullconn;
2584 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002585 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002586 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002588 if (defproxy.check_req) {
2589 curproxy->check_req = calloc(1, defproxy.check_len);
2590 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2591 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002592 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002594 if (defproxy.expect_str) {
2595 curproxy->expect_str = strdup(defproxy.expect_str);
2596 if (defproxy.expect_regex) {
2597 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002598 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2599 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002600 }
2601 }
2602
Willy Tarreau67402132012-05-31 20:40:20 +02002603 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604 if (defproxy.cookie_name)
2605 curproxy->cookie_name = strdup(defproxy.cookie_name);
2606 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002607 if (defproxy.cookie_domain)
2608 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002609
Willy Tarreau31936852010-10-06 16:59:56 +02002610 if (defproxy.cookie_maxidle)
2611 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2612
2613 if (defproxy.cookie_maxlife)
2614 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2615
Emeric Brun647caf12009-06-30 17:57:00 +02002616 if (defproxy.rdp_cookie_name)
2617 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2618 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2619
Willy Tarreau01732802007-11-01 22:48:15 +01002620 if (defproxy.url_param_name)
2621 curproxy->url_param_name = strdup(defproxy.url_param_name);
2622 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002623
Benoitaffb4812009-03-25 13:02:10 +01002624 if (defproxy.hh_name)
2625 curproxy->hh_name = strdup(defproxy.hh_name);
2626 curproxy->hh_len = defproxy.hh_len;
2627 curproxy->hh_match_domain = defproxy.hh_match_domain;
2628
Willy Tarreauef9a3602012-12-08 22:29:20 +01002629 if (defproxy.conn_src.iface_name)
2630 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2631 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002632 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002633#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002634 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002635#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002638 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002639 if (defproxy.capture_name)
2640 curproxy->capture_name = strdup(defproxy.capture_name);
2641 curproxy->capture_namelen = defproxy.capture_namelen;
2642 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002646 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002647 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002648 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002649 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002650 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651 curproxy->mon_net = defproxy.mon_net;
2652 curproxy->mon_mask = defproxy.mon_mask;
2653 if (defproxy.monitor_uri)
2654 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2655 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002656 if (defproxy.defbe.name)
2657 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002658
2659 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002660 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2661 if (curproxy->conf.logformat_string &&
2662 curproxy->conf.logformat_string != default_http_log_format &&
2663 curproxy->conf.logformat_string != default_tcp_log_format &&
2664 curproxy->conf.logformat_string != clf_http_log_format)
2665 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2666
2667 if (defproxy.conf.lfs_file) {
2668 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2669 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2670 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671 }
2672
2673 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002674 curproxy->timeout.connect = defproxy.timeout.connect;
2675 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002676 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002677 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002678 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002679 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002680 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002681 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002682 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002683 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002684 }
2685
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002687 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002688
2689 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002690 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002691 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002692 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002693 LIST_INIT(&node->list);
2694 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2695 }
2696
Willy Tarreau62a61232013-04-12 18:13:46 +02002697 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2698 if (curproxy->conf.uniqueid_format_string)
2699 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2700
Willy Tarreau094af4e2015-01-07 15:03:42 +01002701 if (defproxy.log_tag)
2702 curproxy->log_tag = strdup(defproxy.log_tag);
2703
Willy Tarreau62a61232013-04-12 18:13:46 +02002704 if (defproxy.conf.uif_file) {
2705 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2706 curproxy->conf.uif_line = defproxy.conf.uif_line;
2707 }
William Lallemanda73203e2012-03-12 12:48:57 +01002708
2709 /* copy default header unique id */
2710 if (defproxy.header_unique_id)
2711 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2712
William Lallemand82fe75c2012-10-23 10:25:10 +02002713 /* default compression options */
2714 if (defproxy.comp != NULL) {
2715 curproxy->comp = calloc(1, sizeof(struct comp));
2716 curproxy->comp->algos = defproxy.comp->algos;
2717 curproxy->comp->types = defproxy.comp->types;
2718 }
2719
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002721 curproxy->conf.used_listener_id = EB_ROOT;
2722 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002723
Simon Horman98637e52014-06-20 12:30:16 +09002724 if (defproxy.check_path)
2725 curproxy->check_path = strdup(defproxy.check_path);
2726 if (defproxy.check_command)
2727 curproxy->check_command = strdup(defproxy.check_command);
2728
Simon Horman9dc49962015-01-30 11:22:59 +09002729 if (defproxy.email_alert.mailers.name)
2730 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2731 if (defproxy.email_alert.from)
2732 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2733 if (defproxy.email_alert.to)
2734 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2735 if (defproxy.email_alert.myhostname)
2736 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002737 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002738
Willy Tarreau93893792009-07-23 13:19:11 +02002739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 }
2741 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2742 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002743 /* FIXME-20070101: we should do this too at the end of the
2744 * config parsing to free all default values.
2745 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002746 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2747 err_code |= ERR_ABORT;
2748 goto out;
2749 }
2750
Willy Tarreaua534fea2008-08-03 12:19:50 +02002751 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002752 free(defproxy.check_command);
2753 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002754 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002755 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002756 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002757 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002758 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002759 free(defproxy.capture_name);
2760 free(defproxy.monitor_uri);
2761 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002762 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002763 free(defproxy.fwdfor_hdr_name);
2764 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002765 free(defproxy.orgto_hdr_name);
2766 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002767 free(defproxy.server_id_hdr_name);
2768 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002769 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002770 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002771 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002772 free(defproxy.expect_regex);
2773 defproxy.expect_regex = NULL;
2774 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002775
Willy Tarreau62a61232013-04-12 18:13:46 +02002776 if (defproxy.conf.logformat_string != default_http_log_format &&
2777 defproxy.conf.logformat_string != default_tcp_log_format &&
2778 defproxy.conf.logformat_string != clf_http_log_format)
2779 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002780
Willy Tarreau62a61232013-04-12 18:13:46 +02002781 free(defproxy.conf.uniqueid_format_string);
2782 free(defproxy.conf.lfs_file);
2783 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002784 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002785 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002786
Willy Tarreaua534fea2008-08-03 12:19:50 +02002787 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002788 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002789
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 /* we cannot free uri_auth because it might already be used */
2791 init_default_instance();
2792 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002793 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2794 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 }
2798 else if (curproxy == NULL) {
2799 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002803
2804 /* update the current file and line being parsed */
2805 curproxy->conf.args.file = curproxy->conf.file;
2806 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002807
2808 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002809 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2810 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2811 if (err_code & ERR_FATAL)
2812 goto out;
2813 }
2814 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002815 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002816 int cur_arg;
2817
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 if (curproxy == &defproxy) {
2819 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002823 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825
Willy Tarreau24709282013-03-10 21:32:12 +01002826 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002827 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002832
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002833 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002834
2835 /* use default settings for unix sockets */
2836 bind_conf->ux.uid = global.unix_bind.ux.uid;
2837 bind_conf->ux.gid = global.unix_bind.ux.gid;
2838 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002839
2840 /* NOTE: the following line might create several listeners if there
2841 * are comma-separated IPs or port ranges. So all further processing
2842 * will have to be applied to all listeners created after last_listen.
2843 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002844 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2845 if (errmsg && *errmsg) {
2846 indent_msg(&errmsg, 2);
2847 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002848 }
2849 else
2850 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2851 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002855
Willy Tarreau4348fad2012-09-20 16:48:07 +02002856 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2857 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002858 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002859 }
2860
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002861 cur_arg = 2;
2862 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002863 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002864 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002865 char *err;
2866
Willy Tarreau26982662012-09-12 23:17:10 +02002867 kw = bind_find_kw(args[cur_arg]);
2868 if (kw) {
2869 char *err = NULL;
2870 int code;
2871
2872 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002873 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2874 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002875 cur_arg += 1 + kw->skip ;
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879
Willy Tarreau4348fad2012-09-20 16:48:07 +02002880 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002881 err_code |= code;
2882
2883 if (code) {
2884 if (err && *err) {
2885 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002886 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002887 }
2888 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002889 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2890 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002891 if (code & ERR_FATAL) {
2892 free(err);
2893 cur_arg += 1 + kw->skip;
2894 goto out;
2895 }
2896 }
2897 free(err);
2898 cur_arg += 1 + kw->skip;
2899 continue;
2900 }
2901
Willy Tarreau8638f482012-09-18 18:01:17 +02002902 err = NULL;
2903 if (!bind_dumped) {
2904 bind_dump_kws(&err);
2905 indent_msg(&err, 4);
2906 bind_dumped = 1;
2907 }
2908
2909 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2910 file, linenum, args[0], args[1], args[cur_arg],
2911 err ? " Registered keywords :" : "", err ? err : "");
2912 free(err);
2913
Willy Tarreau93893792009-07-23 13:19:11 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002916 }
Willy Tarreau93893792009-07-23 13:19:11 +02002917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
2919 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002920 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002928
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929 /* flush useless bits */
2930 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002933 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002936
William Lallemanddf1425a2015-04-28 20:17:49 +02002937 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2938 goto out;
2939
Willy Tarreau1c47f852006-07-09 08:22:27 +02002940 if (!*args[1]) {
2941 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002945 }
2946
Willy Tarreaua534fea2008-08-03 12:19:50 +02002947 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002948 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002949 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002950 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002951 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2952
Willy Tarreau93893792009-07-23 13:19:11 +02002953 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2957 goto out;
2958
Willy Tarreaubaaee002006-06-26 02:48:02 +02002959 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2960 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2961 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2962 else {
2963 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002968 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002969 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002970
2971 if (curproxy == &defproxy) {
2972 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002976 }
2977
William Lallemanddf1425a2015-04-28 20:17:49 +02002978 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2979 goto out;
2980
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002981 if (!*args[1]) {
2982 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2983 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002986 }
2987
2988 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002989 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002990 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002991
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002992 if (curproxy->uuid <= 0) {
2993 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002994 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002997 }
2998
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002999 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3000 if (node) {
3001 struct proxy *target = container_of(node, struct proxy, conf.id);
3002 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3003 file, linenum, proxy_type_str(curproxy), curproxy->id,
3004 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003009 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003010 else if (!strcmp(args[0], "description")) {
3011 int i, len=0;
3012 char *d;
3013
Cyril Bonté99ed3272010-01-24 23:29:44 +01003014 if (curproxy == &defproxy) {
3015 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3016 file, linenum, args[0]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003021 if (!*args[1]) {
3022 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3023 file, linenum, args[0]);
3024 return -1;
3025 }
3026
Willy Tarreau348acfe2014-04-14 15:00:39 +02003027 for (i = 1; *args[i]; i++)
3028 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003029
3030 d = (char *)calloc(1, len);
3031 curproxy->desc = d;
3032
Willy Tarreau348acfe2014-04-14 15:00:39 +02003033 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3034 for (i = 2; *args[i]; i++)
3035 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003036
3037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003039 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 curproxy->state = PR_STSTOPPED;
3042 }
3043 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003044 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 curproxy->state = PR_STNEW;
3047 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003048 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3049 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003050 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003051
3052 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003053 unsigned int low, high;
3054
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003055 if (strcmp(args[cur_arg], "all") == 0) {
3056 set = 0;
3057 break;
3058 }
3059 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003060 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003061 }
3062 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003063 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003064 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003065 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003066 char *dash = strchr(args[cur_arg], '-');
3067
3068 low = high = str2uic(args[cur_arg]);
3069 if (dash)
3070 high = str2uic(dash + 1);
3071
3072 if (high < low) {
3073 unsigned int swap = low;
3074 low = high;
3075 high = swap;
3076 }
3077
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003078 if (low < 1 || high > LONGBITS) {
3079 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3080 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003083 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003084 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003085 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003086 }
3087 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003088 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3089 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003092 }
3093 cur_arg++;
3094 }
3095 curproxy->bind_proc = set;
3096 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003097 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003098 if (curproxy == &defproxy) {
3099 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003102 }
3103
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003104 err = invalid_char(args[1]);
3105 if (err) {
3106 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3107 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003109 }
3110
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003111 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003112 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3113 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003116 }
3117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3119 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120
Willy Tarreau977b8e42006-12-29 14:19:17 +01003121 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003123
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 if (*(args[1]) == 0) {
3125 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3126 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003130
Willy Tarreau67402132012-05-31 20:40:20 +02003131 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003132 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003133 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003134 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 curproxy->cookie_name = strdup(args[1]);
3136 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003137
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 cur_arg = 2;
3139 while (*(args[cur_arg])) {
3140 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003141 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 }
3143 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003144 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
3146 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003147 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
3149 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003150 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 }
3152 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003153 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003155 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003156 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003159 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003161 else if (!strcmp(args[cur_arg], "httponly")) {
3162 curproxy->ck_opts |= PR_CK_HTTPONLY;
3163 }
3164 else if (!strcmp(args[cur_arg], "secure")) {
3165 curproxy->ck_opts |= PR_CK_SECURE;
3166 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003167 else if (!strcmp(args[cur_arg], "domain")) {
3168 if (!*args[cur_arg + 1]) {
3169 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3170 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003173 }
3174
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003175 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003176 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003177 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3178 " dots nor does not start with a dot."
3179 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003180 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003181 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003182 }
3183
3184 err = invalid_domainchar(args[cur_arg + 1]);
3185 if (err) {
3186 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3187 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003190 }
3191
Willy Tarreau68a897b2009-12-03 23:28:34 +01003192 if (!curproxy->cookie_domain) {
3193 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3194 } else {
3195 /* one domain was already specified, add another one by
3196 * building the string which will be returned along with
3197 * the cookie.
3198 */
3199 char *new_ptr;
3200 int new_len = strlen(curproxy->cookie_domain) +
3201 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3202 new_ptr = malloc(new_len);
3203 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3204 free(curproxy->cookie_domain);
3205 curproxy->cookie_domain = new_ptr;
3206 }
Willy Tarreau31936852010-10-06 16:59:56 +02003207 cur_arg++;
3208 }
3209 else if (!strcmp(args[cur_arg], "maxidle")) {
3210 unsigned int maxidle;
3211 const char *res;
3212
3213 if (!*args[cur_arg + 1]) {
3214 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3215 file, linenum, args[cur_arg]);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
3219
3220 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3221 if (res) {
3222 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3223 file, linenum, *res, args[cur_arg]);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
3227 curproxy->cookie_maxidle = maxidle;
3228 cur_arg++;
3229 }
3230 else if (!strcmp(args[cur_arg], "maxlife")) {
3231 unsigned int maxlife;
3232 const char *res;
3233
3234 if (!*args[cur_arg + 1]) {
3235 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3236 file, linenum, args[cur_arg]);
3237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
3239 }
3240
3241 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3242 if (res) {
3243 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3244 file, linenum, *res, args[cur_arg]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003249 cur_arg++;
3250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003252 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 +02003253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 }
3257 cur_arg++;
3258 }
Willy Tarreau67402132012-05-31 20:40:20 +02003259 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3261 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
3264
Willy Tarreau67402132012-05-31 20:40:20 +02003265 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3267 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003268 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003270
Willy Tarreau67402132012-05-31 20:40:20 +02003271 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003272 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3273 file, linenum);
3274 err_code |= ERR_ALERT | ERR_FATAL;
3275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003277 else if (!strcmp(args[0], "email-alert")) {
3278 if (*(args[1]) == 0) {
3279 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3280 file, linenum, args[0]);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283 }
3284
3285 if (!strcmp(args[1], "from")) {
3286 if (*(args[1]) == 0) {
3287 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3288 file, linenum, args[1]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
3291 }
3292 free(curproxy->email_alert.from);
3293 curproxy->email_alert.from = strdup(args[2]);
3294 }
3295 else if (!strcmp(args[1], "mailers")) {
3296 if (*(args[1]) == 0) {
3297 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3298 file, linenum, args[1]);
3299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
3301 }
3302 free(curproxy->email_alert.mailers.name);
3303 curproxy->email_alert.mailers.name = strdup(args[2]);
3304 }
3305 else if (!strcmp(args[1], "myhostname")) {
3306 if (*(args[1]) == 0) {
3307 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3308 file, linenum, args[1]);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
3311 }
3312 free(curproxy->email_alert.myhostname);
3313 curproxy->email_alert.myhostname = strdup(args[2]);
3314 }
Simon Horman64e34162015-02-06 11:11:57 +09003315 else if (!strcmp(args[1], "level")) {
3316 curproxy->email_alert.level = get_log_level(args[2]);
3317 if (curproxy->email_alert.level < 0) {
3318 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3319 file, linenum, args[1], args[2]);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322 }
3323 }
Simon Horman9dc49962015-01-30 11:22:59 +09003324 else if (!strcmp(args[1], "to")) {
3325 if (*(args[1]) == 0) {
3326 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3327 file, linenum, args[1]);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
3331 free(curproxy->email_alert.to);
3332 curproxy->email_alert.to = strdup(args[2]);
3333 }
3334 else {
3335 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3336 file, linenum, args[1]);
3337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
3339 }
Simon Horman64e34162015-02-06 11:11:57 +09003340 /* Indicate that the email_alert is at least partially configured */
3341 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003342 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003343 else if (!strcmp(args[0], "external-check")) {
3344 if (*(args[1]) == 0) {
3345 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3346 file, linenum, args[0]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350
3351 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003352 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3353 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003354 if (*(args[1]) == 0) {
3355 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3356 file, linenum, args[1]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360 free(curproxy->check_command);
3361 curproxy->check_command = strdup(args[2]);
3362 }
3363 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003364 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3365 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003366 if (*(args[1]) == 0) {
3367 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3368 file, linenum, args[1]);
3369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
3371 }
3372 free(curproxy->check_path);
3373 curproxy->check_path = strdup(args[2]);
3374 }
3375 else {
3376 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3377 file, linenum, args[1]);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
3381 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003382 else if (!strcmp(args[0], "persist")) { /* persist */
3383 if (*(args[1]) == 0) {
3384 Alert("parsing [%s:%d] : missing persist method.\n",
3385 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003388 }
3389
3390 if (!strncmp(args[1], "rdp-cookie", 10)) {
3391 curproxy->options2 |= PR_O2_RDPC_PRST;
3392
Emeric Brunb982a3d2010-01-04 15:45:53 +01003393 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003394 const char *beg, *end;
3395
3396 beg = args[1] + 11;
3397 end = strchr(beg, ')');
3398
William Lallemanddf1425a2015-04-28 20:17:49 +02003399 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3400 goto out;
3401
Emeric Brun647caf12009-06-30 17:57:00 +02003402 if (!end || end == beg) {
3403 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3404 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003407 }
3408
3409 free(curproxy->rdp_cookie_name);
3410 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3411 curproxy->rdp_cookie_len = end-beg;
3412 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003413 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003414 free(curproxy->rdp_cookie_name);
3415 curproxy->rdp_cookie_name = strdup("msts");
3416 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3417 }
3418 else { /* syntax */
3419 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3420 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003423 }
3424 }
3425 else {
3426 Alert("parsing [%s:%d] : unknown persist method.\n",
3427 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003430 }
3431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003433 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3434 err_code |= ERR_ALERT | ERR_FATAL;
3435 goto out;
3436 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003437 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003438 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003439 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003440
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003442 if (curproxy == &defproxy) {
3443 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3444 err_code |= ERR_ALERT | ERR_FATAL;
3445 goto out;
3446 }
3447
William Lallemand1a748ae2015-05-19 16:37:23 +02003448 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3449 goto out;
3450
Willy Tarreaubaaee002006-06-26 02:48:02 +02003451 if (*(args[4]) == 0) {
3452 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3453 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003456 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003457 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003458 curproxy->capture_name = strdup(args[2]);
3459 curproxy->capture_namelen = strlen(curproxy->capture_name);
3460 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 curproxy->to_log |= LW_COOKIE;
3462 }
3463 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3464 struct cap_hdr *hdr;
3465
3466 if (curproxy == &defproxy) {
3467 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 +02003468 err_code |= ERR_ALERT | ERR_FATAL;
3469 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003470 }
3471
William Lallemand1a748ae2015-05-19 16:37:23 +02003472 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3473 goto out;
3474
Willy Tarreaubaaee002006-06-26 02:48:02 +02003475 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3476 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3477 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003478 err_code |= ERR_ALERT | ERR_FATAL;
3479 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003480 }
3481
3482 hdr = calloc(sizeof(struct cap_hdr), 1);
3483 hdr->next = curproxy->req_cap;
3484 hdr->name = strdup(args[3]);
3485 hdr->namelen = strlen(args[3]);
3486 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003487 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003488 hdr->index = curproxy->nb_req_cap++;
3489 curproxy->req_cap = hdr;
3490 curproxy->to_log |= LW_REQHDR;
3491 }
3492 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3493 struct cap_hdr *hdr;
3494
3495 if (curproxy == &defproxy) {
3496 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 +02003497 err_code |= ERR_ALERT | ERR_FATAL;
3498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 }
3500
William Lallemand1a748ae2015-05-19 16:37:23 +02003501 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3502 goto out;
3503
Willy Tarreaubaaee002006-06-26 02:48:02 +02003504 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3505 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3506 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003507 err_code |= ERR_ALERT | ERR_FATAL;
3508 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003509 }
3510 hdr = calloc(sizeof(struct cap_hdr), 1);
3511 hdr->next = curproxy->rsp_cap;
3512 hdr->name = strdup(args[3]);
3513 hdr->namelen = strlen(args[3]);
3514 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003515 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003516 hdr->index = curproxy->nb_rsp_cap++;
3517 curproxy->rsp_cap = hdr;
3518 curproxy->to_log |= LW_RSPHDR;
3519 }
3520 else {
3521 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3522 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003523 err_code |= ERR_ALERT | ERR_FATAL;
3524 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003525 }
3526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003528 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003529 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003530
William Lallemanddf1425a2015-04-28 20:17:49 +02003531 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3532 goto out;
3533
Willy Tarreaubaaee002006-06-26 02:48:02 +02003534 if (*(args[1]) == 0) {
3535 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3536 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }
3540 curproxy->conn_retries = atol(args[1]);
3541 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003542 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003543 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003544
3545 if (curproxy == &defproxy) {
3546 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3547 err_code |= ERR_ALERT | ERR_FATAL;
3548 goto out;
3549 }
3550
Willy Tarreau20b0de52012-12-24 15:45:22 +01003551 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003552 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003553 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3554 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3555 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3556 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003557 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 +01003558 file, linenum, args[0]);
3559 err_code |= ERR_WARN;
3560 }
3561
Willy Tarreauff011f22011-01-06 17:51:27 +01003562 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003563
Willy Tarreauff011f22011-01-06 17:51:27 +01003564 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003565 err_code |= ERR_ALERT | ERR_ABORT;
3566 goto out;
3567 }
3568
Willy Tarreau5002f572014-04-23 01:32:02 +02003569 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003570 err_code |= warnif_cond_conflicts(rule->cond,
3571 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3572 file, linenum);
3573
Willy Tarreauff011f22011-01-06 17:51:27 +01003574 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003575 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003576 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003577 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003578
3579 if (curproxy == &defproxy) {
3580 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3581 err_code |= ERR_ALERT | ERR_FATAL;
3582 goto out;
3583 }
3584
3585 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003586 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003587 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3588 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003589 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3590 file, linenum, args[0]);
3591 err_code |= ERR_WARN;
3592 }
3593
3594 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3595
3596 if (!rule) {
3597 err_code |= ERR_ALERT | ERR_ABORT;
3598 goto out;
3599 }
3600
3601 err_code |= warnif_cond_conflicts(rule->cond,
3602 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3603 file, linenum);
3604
3605 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3606 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003607 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3608 /* set the header name and length into the proxy structure */
3609 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3610 err_code |= ERR_WARN;
3611
3612 if (!*args[1]) {
3613 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3614 file, linenum, args[0]);
3615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
3617 }
3618
3619 /* set the desired header name */
3620 free(curproxy->server_id_hdr_name);
3621 curproxy->server_id_hdr_name = strdup(args[1]);
3622 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3623 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003624 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003625 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003626
Willy Tarreaub099aca2008-10-12 17:26:37 +02003627 if (curproxy == &defproxy) {
3628 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003629 err_code |= ERR_ALERT | ERR_FATAL;
3630 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003631 }
3632
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003633 /* emulate "block" using "http-request block". Since these rules are supposed to
3634 * be processed before all http-request rules, we put them into their own list
3635 * and will insert them at the end.
3636 */
3637 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3638 if (!rule) {
3639 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003640 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003641 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003642 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3643 err_code |= warnif_cond_conflicts(rule->cond,
3644 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3645 file, linenum);
3646 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003647
3648 if (!already_warned(WARN_BLOCK_DEPRECATED))
3649 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]);
3650
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003651 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003652 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003653 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003654
Cyril Bonté99ed3272010-01-24 23:29:44 +01003655 if (curproxy == &defproxy) {
3656 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3657 err_code |= ERR_ALERT | ERR_FATAL;
3658 goto out;
3659 }
3660
Willy Tarreaube4653b2015-05-28 15:26:58 +02003661 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003662 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3663 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003666 }
3667
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003668 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003669 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003670 err_code |= warnif_cond_conflicts(rule->cond,
3671 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3672 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003673 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003674 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003675 struct switching_rule *rule;
3676
Willy Tarreaub099aca2008-10-12 17:26:37 +02003677 if (curproxy == &defproxy) {
3678 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003679 err_code |= ERR_ALERT | ERR_FATAL;
3680 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003681 }
3682
Willy Tarreau55ea7572007-06-17 19:56:27 +02003683 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003684 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003685
3686 if (*(args[1]) == 0) {
3687 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003690 }
3691
Willy Tarreauf51658d2014-04-23 01:21:56 +02003692 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3693 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3694 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3695 file, linenum, errmsg);
3696 err_code |= ERR_ALERT | ERR_FATAL;
3697 goto out;
3698 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003699
Willy Tarreauf51658d2014-04-23 01:21:56 +02003700 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003701 }
3702
3703 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3704 rule->cond = cond;
3705 rule->be.name = strdup(args[1]);
3706 LIST_INIT(&rule->list);
3707 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3708 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003709 else if (strcmp(args[0], "use-server") == 0) {
3710 struct server_rule *rule;
3711
3712 if (curproxy == &defproxy) {
3713 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3714 err_code |= ERR_ALERT | ERR_FATAL;
3715 goto out;
3716 }
3717
3718 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3719 err_code |= ERR_WARN;
3720
3721 if (*(args[1]) == 0) {
3722 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726
3727 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3728 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3729 file, linenum, args[0]);
3730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
3732 }
3733
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003734 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3735 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3736 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
3739 }
3740
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003741 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003742
3743 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3744 rule->cond = cond;
3745 rule->srv.name = strdup(args[1]);
3746 LIST_INIT(&rule->list);
3747 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3748 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3749 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003750 else if ((!strcmp(args[0], "force-persist")) ||
3751 (!strcmp(args[0], "ignore-persist"))) {
3752 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003753
3754 if (curproxy == &defproxy) {
3755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3756 err_code |= ERR_ALERT | ERR_FATAL;
3757 goto out;
3758 }
3759
3760 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3761 err_code |= ERR_WARN;
3762
Willy Tarreauef6494c2010-01-28 17:12:36 +01003763 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003764 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3765 file, linenum, args[0]);
3766 err_code |= ERR_ALERT | ERR_FATAL;
3767 goto out;
3768 }
3769
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003770 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3771 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3772 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003773 err_code |= ERR_ALERT | ERR_FATAL;
3774 goto out;
3775 }
3776
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003777 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3778 * where force-persist is applied.
3779 */
3780 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003781
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003782 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003783 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003784 if (!strcmp(args[0], "force-persist")) {
3785 rule->type = PERSIST_TYPE_FORCE;
3786 } else {
3787 rule->type = PERSIST_TYPE_IGNORE;
3788 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003789 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003790 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003791 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003792 else if (!strcmp(args[0], "stick-table")) {
3793 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003794 struct proxy *other;
3795
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003796 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003797 if (other) {
3798 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3799 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
3802 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003803
Emeric Brun32da3c42010-09-23 18:39:19 +02003804 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003805 curproxy->table.type = (unsigned int)-1;
3806 while (*args[myidx]) {
3807 const char *err;
3808
3809 if (strcmp(args[myidx], "size") == 0) {
3810 myidx++;
3811 if (!*(args[myidx])) {
3812 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3813 file, linenum, args[myidx-1]);
3814 err_code |= ERR_ALERT | ERR_FATAL;
3815 goto out;
3816 }
3817 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3818 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3819 file, linenum, *err, args[myidx-1]);
3820 err_code |= ERR_ALERT | ERR_FATAL;
3821 goto out;
3822 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003823 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003824 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003825 else if (strcmp(args[myidx], "peers") == 0) {
3826 myidx++;
Godbach50523162013-12-11 19:48:57 +08003827 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003828 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3829 file, linenum, args[myidx-1]);
3830 err_code |= ERR_ALERT | ERR_FATAL;
3831 goto out;
Godbach50523162013-12-11 19:48:57 +08003832 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003833 curproxy->table.peers.name = strdup(args[myidx++]);
3834 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003835 else if (strcmp(args[myidx], "expire") == 0) {
3836 myidx++;
3837 if (!*(args[myidx])) {
3838 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3839 file, linenum, args[myidx-1]);
3840 err_code |= ERR_ALERT | ERR_FATAL;
3841 goto out;
3842 }
3843 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3844 if (err) {
3845 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3846 file, linenum, *err, args[myidx-1]);
3847 err_code |= ERR_ALERT | ERR_FATAL;
3848 goto out;
3849 }
3850 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003851 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003852 }
3853 else if (strcmp(args[myidx], "nopurge") == 0) {
3854 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003855 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003856 }
3857 else if (strcmp(args[myidx], "type") == 0) {
3858 myidx++;
3859 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3860 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3861 file, linenum, args[myidx]);
3862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
3864 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003865 /* myidx already points to next arg */
3866 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003867 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003868 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003869 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003870
3871 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003872 nw = args[myidx];
3873 while (*nw) {
3874 /* the "store" keyword supports a comma-separated list */
3875 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003876 sa = NULL; /* store arg */
3877 while (*nw && *nw != ',') {
3878 if (*nw == '(') {
3879 *nw = 0;
3880 sa = ++nw;
3881 while (*nw != ')') {
3882 if (!*nw) {
3883 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3884 file, linenum, args[0], cw);
3885 err_code |= ERR_ALERT | ERR_FATAL;
3886 goto out;
3887 }
3888 nw++;
3889 }
3890 *nw = '\0';
3891 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003892 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003893 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003894 if (*nw)
3895 *nw++ = '\0';
3896 type = stktable_get_data_type(cw);
3897 if (type < 0) {
3898 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3899 file, linenum, args[0], cw);
3900 err_code |= ERR_ALERT | ERR_FATAL;
3901 goto out;
3902 }
Willy Tarreauac782882010-06-20 10:41:54 +02003903
3904 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3905 switch (err) {
3906 case PE_NONE: break;
3907 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003908 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3909 file, linenum, args[0], cw);
3910 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003911 break;
3912
3913 case PE_ARG_MISSING:
3914 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3915 file, linenum, args[0], cw);
3916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918
3919 case PE_ARG_NOT_USED:
3920 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3921 file, linenum, args[0], cw);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
3924
3925 default:
3926 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3927 file, linenum, args[0], cw);
3928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003930 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003931 }
3932 myidx++;
3933 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003934 else {
3935 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3936 file, linenum, args[myidx]);
3937 err_code |= ERR_ALERT | ERR_FATAL;
3938 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003939 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003940 }
3941
3942 if (!curproxy->table.size) {
3943 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3944 file, linenum);
3945 err_code |= ERR_ALERT | ERR_FATAL;
3946 goto out;
3947 }
3948
3949 if (curproxy->table.type == (unsigned int)-1) {
3950 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3951 file, linenum);
3952 err_code |= ERR_ALERT | ERR_FATAL;
3953 goto out;
3954 }
3955 }
3956 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003957 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003958 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003959 int myidx = 0;
3960 const char *name = NULL;
3961 int flags;
3962
3963 if (curproxy == &defproxy) {
3964 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3965 err_code |= ERR_ALERT | ERR_FATAL;
3966 goto out;
3967 }
3968
3969 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3970 err_code |= ERR_WARN;
3971 goto out;
3972 }
3973
3974 myidx++;
3975 if ((strcmp(args[myidx], "store") == 0) ||
3976 (strcmp(args[myidx], "store-request") == 0)) {
3977 myidx++;
3978 flags = STK_IS_STORE;
3979 }
3980 else if (strcmp(args[myidx], "store-response") == 0) {
3981 myidx++;
3982 flags = STK_IS_STORE | STK_ON_RSP;
3983 }
3984 else if (strcmp(args[myidx], "match") == 0) {
3985 myidx++;
3986 flags = STK_IS_MATCH;
3987 }
3988 else if (strcmp(args[myidx], "on") == 0) {
3989 myidx++;
3990 flags = STK_IS_MATCH | STK_IS_STORE;
3991 }
3992 else {
3993 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
3996 }
3997
3998 if (*(args[myidx]) == 0) {
3999 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
4002 }
4003
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004004 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004005 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004006 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004007 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
4011
4012 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004013 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4014 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4015 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004016 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004017 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004018 goto out;
4019 }
4020 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004021 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4022 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4023 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004024 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004025 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004026 goto out;
4027 }
4028 }
4029
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004030 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004031 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004032
Emeric Brunb982a3d2010-01-04 15:45:53 +01004033 if (strcmp(args[myidx], "table") == 0) {
4034 myidx++;
4035 name = args[myidx++];
4036 }
4037
Willy Tarreauef6494c2010-01-28 17:12:36 +01004038 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004039 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4040 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4041 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004042 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004043 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004044 goto out;
4045 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004046 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004047 else if (*(args[myidx])) {
4048 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4049 file, linenum, args[0], args[myidx]);
4050 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004051 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004052 goto out;
4053 }
Emeric Brun97679e72010-09-23 17:56:44 +02004054 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004055 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004056 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004057 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004058
Emeric Brunb982a3d2010-01-04 15:45:53 +01004059 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4060 rule->cond = cond;
4061 rule->expr = expr;
4062 rule->flags = flags;
4063 rule->table.name = name ? strdup(name) : NULL;
4064 LIST_INIT(&rule->list);
4065 if (flags & STK_ON_RSP)
4066 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4067 else
4068 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4069 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004070 else if (!strcmp(args[0], "stats")) {
4071 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4072 curproxy->uri_auth = NULL; /* we must detach from the default config */
4073
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004074 if (!*args[1]) {
4075 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004076 } else if (!strcmp(args[1], "admin")) {
4077 struct stats_admin_rule *rule;
4078
4079 if (curproxy == &defproxy) {
4080 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4081 err_code |= ERR_ALERT | ERR_FATAL;
4082 goto out;
4083 }
4084
4085 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4086 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4087 err_code |= ERR_ALERT | ERR_ABORT;
4088 goto out;
4089 }
4090
4091 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4092 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4093 file, linenum, args[0], args[1]);
4094 err_code |= ERR_ALERT | ERR_FATAL;
4095 goto out;
4096 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004097 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4098 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4099 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004100 err_code |= ERR_ALERT | ERR_FATAL;
4101 goto out;
4102 }
4103
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004104 err_code |= warnif_cond_conflicts(cond,
4105 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4106 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004107
4108 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4109 rule->cond = cond;
4110 LIST_INIT(&rule->list);
4111 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004112 } else if (!strcmp(args[1], "uri")) {
4113 if (*(args[2]) == 0) {
4114 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004119 err_code |= ERR_ALERT | ERR_ABORT;
4120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 }
4122 } else if (!strcmp(args[1], "realm")) {
4123 if (*(args[2]) == 0) {
4124 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004125 err_code |= ERR_ALERT | ERR_FATAL;
4126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4128 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004129 err_code |= ERR_ALERT | ERR_ABORT;
4130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004131 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004132 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004133 unsigned interval;
4134
4135 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4136 if (err) {
4137 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4138 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004141 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4142 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004143 err_code |= ERR_ALERT | ERR_ABORT;
4144 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004145 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004146 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004147 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004148
4149 if (curproxy == &defproxy) {
4150 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4151 err_code |= ERR_ALERT | ERR_FATAL;
4152 goto out;
4153 }
4154
4155 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4156 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4157 err_code |= ERR_ALERT | ERR_ABORT;
4158 goto out;
4159 }
4160
Willy Tarreauff011f22011-01-06 17:51:27 +01004161 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004162 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004163 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4164 file, linenum, args[0]);
4165 err_code |= ERR_WARN;
4166 }
4167
Willy Tarreauff011f22011-01-06 17:51:27 +01004168 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004169
Willy Tarreauff011f22011-01-06 17:51:27 +01004170 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004171 err_code |= ERR_ALERT | ERR_ABORT;
4172 goto out;
4173 }
4174
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004175 err_code |= warnif_cond_conflicts(rule->cond,
4176 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4177 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004178 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004179
Willy Tarreaubaaee002006-06-26 02:48:02 +02004180 } else if (!strcmp(args[1], "auth")) {
4181 if (*(args[2]) == 0) {
4182 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004183 err_code |= ERR_ALERT | ERR_FATAL;
4184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004185 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4186 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004187 err_code |= ERR_ALERT | ERR_ABORT;
4188 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004189 }
4190 } else if (!strcmp(args[1], "scope")) {
4191 if (*(args[2]) == 0) {
4192 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004193 err_code |= ERR_ALERT | ERR_FATAL;
4194 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004195 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4196 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004197 err_code |= ERR_ALERT | ERR_ABORT;
4198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004199 }
4200 } else if (!strcmp(args[1], "enable")) {
4201 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4202 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004203 err_code |= ERR_ALERT | ERR_ABORT;
4204 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004205 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004206 } else if (!strcmp(args[1], "hide-version")) {
4207 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004209 err_code |= ERR_ALERT | ERR_ABORT;
4210 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004211 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004212 } else if (!strcmp(args[1], "show-legends")) {
4213 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4214 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4215 err_code |= ERR_ALERT | ERR_ABORT;
4216 goto out;
4217 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004218 } else if (!strcmp(args[1], "show-node")) {
4219
4220 if (*args[2]) {
4221 int i;
4222 char c;
4223
4224 for (i=0; args[2][i]; i++) {
4225 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004226 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4227 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004228 break;
4229 }
4230
4231 if (!i || args[2][i]) {
4232 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4233 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4234 file, linenum, args[0], args[1]);
4235 err_code |= ERR_ALERT | ERR_FATAL;
4236 goto out;
4237 }
4238 }
4239
4240 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4241 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4242 err_code |= ERR_ALERT | ERR_ABORT;
4243 goto out;
4244 }
4245 } else if (!strcmp(args[1], "show-desc")) {
4246 char *desc = NULL;
4247
4248 if (*args[2]) {
4249 int i, len=0;
4250 char *d;
4251
Willy Tarreau348acfe2014-04-14 15:00:39 +02004252 for (i = 2; *args[i]; i++)
4253 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004254
4255 desc = d = (char *)calloc(1, len);
4256
Willy Tarreau348acfe2014-04-14 15:00:39 +02004257 d += snprintf(d, desc + len - d, "%s", args[2]);
4258 for (i = 3; *args[i]; i++)
4259 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004260 }
4261
4262 if (!*args[2] && !global.desc)
4263 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4264 file, linenum, args[1]);
4265 else {
4266 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4267 free(desc);
4268 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4269 err_code |= ERR_ALERT | ERR_ABORT;
4270 goto out;
4271 }
4272 free(desc);
4273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004275stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004276 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 +01004277 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004278 err_code |= ERR_ALERT | ERR_FATAL;
4279 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004280 }
4281 }
4282 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004283 int optnum;
4284
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004285 if (*(args[1]) == '\0') {
4286 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4287 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004288 err_code |= ERR_ALERT | ERR_FATAL;
4289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004290 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004291
4292 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4293 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004294 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4295 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4296 file, linenum, cfg_opts[optnum].name);
4297 err_code |= ERR_ALERT | ERR_FATAL;
4298 goto out;
4299 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004300 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4301 goto out;
4302
Willy Tarreau93893792009-07-23 13:19:11 +02004303 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4304 err_code |= ERR_WARN;
4305 goto out;
4306 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004307
Willy Tarreau3842f002009-06-14 11:39:52 +02004308 curproxy->no_options &= ~cfg_opts[optnum].val;
4309 curproxy->options &= ~cfg_opts[optnum].val;
4310
4311 switch (kwm) {
4312 case KWM_STD:
4313 curproxy->options |= cfg_opts[optnum].val;
4314 break;
4315 case KWM_NO:
4316 curproxy->no_options |= cfg_opts[optnum].val;
4317 break;
4318 case KWM_DEF: /* already cleared */
4319 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004320 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004321
Willy Tarreau93893792009-07-23 13:19:11 +02004322 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004323 }
4324 }
4325
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004326 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4327 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004328 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4329 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4330 file, linenum, cfg_opts2[optnum].name);
4331 err_code |= ERR_ALERT | ERR_FATAL;
4332 goto out;
4333 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004334 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4335 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004336 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4337 err_code |= ERR_WARN;
4338 goto out;
4339 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004340
Willy Tarreau3842f002009-06-14 11:39:52 +02004341 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4342 curproxy->options2 &= ~cfg_opts2[optnum].val;
4343
4344 switch (kwm) {
4345 case KWM_STD:
4346 curproxy->options2 |= cfg_opts2[optnum].val;
4347 break;
4348 case KWM_NO:
4349 curproxy->no_options2 |= cfg_opts2[optnum].val;
4350 break;
4351 case KWM_DEF: /* already cleared */
4352 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004353 }
Willy Tarreau93893792009-07-23 13:19:11 +02004354 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004355 }
4356 }
4357
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004358 /* HTTP options override each other. They can be cancelled using
4359 * "no option xxx" which only switches to default mode if the mode
4360 * was this one (useful for cancelling options set in defaults
4361 * sections).
4362 */
4363 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004364 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4365 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004366 if (kwm == KWM_STD) {
4367 curproxy->options &= ~PR_O_HTTP_MODE;
4368 curproxy->options |= PR_O_HTTP_PCL;
4369 goto out;
4370 }
4371 else if (kwm == KWM_NO) {
4372 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4373 curproxy->options &= ~PR_O_HTTP_MODE;
4374 goto out;
4375 }
4376 }
4377 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004378 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4379 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004380 if (kwm == KWM_STD) {
4381 curproxy->options &= ~PR_O_HTTP_MODE;
4382 curproxy->options |= PR_O_HTTP_FCL;
4383 goto out;
4384 }
4385 else if (kwm == KWM_NO) {
4386 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4387 curproxy->options &= ~PR_O_HTTP_MODE;
4388 goto out;
4389 }
4390 }
4391 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004392 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4393 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004394 if (kwm == KWM_STD) {
4395 curproxy->options &= ~PR_O_HTTP_MODE;
4396 curproxy->options |= PR_O_HTTP_SCL;
4397 goto out;
4398 }
4399 else if (kwm == KWM_NO) {
4400 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4401 curproxy->options &= ~PR_O_HTTP_MODE;
4402 goto out;
4403 }
4404 }
4405 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004406 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4407 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004408 if (kwm == KWM_STD) {
4409 curproxy->options &= ~PR_O_HTTP_MODE;
4410 curproxy->options |= PR_O_HTTP_KAL;
4411 goto out;
4412 }
4413 else if (kwm == KWM_NO) {
4414 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4415 curproxy->options &= ~PR_O_HTTP_MODE;
4416 goto out;
4417 }
4418 }
4419 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004420 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4421 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004422 if (kwm == KWM_STD) {
4423 curproxy->options &= ~PR_O_HTTP_MODE;
4424 curproxy->options |= PR_O_HTTP_TUN;
4425 goto out;
4426 }
4427 else if (kwm == KWM_NO) {
4428 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4429 curproxy->options &= ~PR_O_HTTP_MODE;
4430 goto out;
4431 }
4432 }
4433
Joseph Lynch726ab712015-05-11 23:25:34 -07004434 /* Redispatch can take an integer argument that control when the
4435 * resispatch occurs. All values are relative to the retries option.
4436 * This can be cancelled using "no option xxx".
4437 */
4438 if (strcmp(args[1], "redispatch") == 0) {
4439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4440 err_code |= ERR_WARN;
4441 goto out;
4442 }
4443
4444 curproxy->no_options &= ~PR_O_REDISP;
4445 curproxy->options &= ~PR_O_REDISP;
4446
4447 switch (kwm) {
4448 case KWM_STD:
4449 curproxy->options |= PR_O_REDISP;
4450 curproxy->redispatch_after = -1;
4451 if(*args[2]) {
4452 curproxy->redispatch_after = atol(args[2]);
4453 }
4454 break;
4455 case KWM_NO:
4456 curproxy->no_options |= PR_O_REDISP;
4457 curproxy->redispatch_after = 0;
4458 break;
4459 case KWM_DEF: /* already cleared */
4460 break;
4461 }
4462 goto out;
4463 }
4464
Willy Tarreau3842f002009-06-14 11:39:52 +02004465 if (kwm != KWM_STD) {
4466 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004467 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004468 err_code |= ERR_ALERT | ERR_FATAL;
4469 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004470 }
4471
Emeric Brun3a058f32009-06-30 18:26:00 +02004472 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004473 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004475 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004476 if (*(args[2]) != '\0') {
4477 if (!strcmp(args[2], "clf")) {
4478 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004479 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004480 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004481 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004484 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004485 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4486 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004487 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004488 if (curproxy->conf.logformat_string != default_http_log_format &&
4489 curproxy->conf.logformat_string != default_tcp_log_format &&
4490 curproxy->conf.logformat_string != clf_http_log_format)
4491 free(curproxy->conf.logformat_string);
4492 curproxy->conf.logformat_string = logformat;
4493
4494 free(curproxy->conf.lfs_file);
4495 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4496 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004497 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004498 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004499 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004500 if (curproxy->conf.logformat_string != default_http_log_format &&
4501 curproxy->conf.logformat_string != default_tcp_log_format &&
4502 curproxy->conf.logformat_string != clf_http_log_format)
4503 free(curproxy->conf.logformat_string);
4504 curproxy->conf.logformat_string = default_tcp_log_format;
4505
4506 free(curproxy->conf.lfs_file);
4507 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4508 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004509
4510 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4511 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004512 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004513 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004514 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004515 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004516 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004517
William Lallemanddf1425a2015-04-28 20:17:49 +02004518 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4519 goto out;
4520
Willy Tarreau13943ab2006-12-31 00:24:10 +01004521 if (curproxy->cap & PR_CAP_FE)
4522 curproxy->options |= PR_O_TCP_CLI_KA;
4523 if (curproxy->cap & PR_CAP_BE)
4524 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004525 }
4526 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004527 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004528 err_code |= ERR_WARN;
4529
Willy Tarreaubaaee002006-06-26 02:48:02 +02004530 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004531 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004532 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004533 curproxy->options2 &= ~PR_O2_CHK_ANY;
4534 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004535 if (!*args[2]) { /* no argument */
4536 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4537 curproxy->check_len = strlen(DEF_CHECK_REQ);
4538 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004539 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 curproxy->check_req = (char *)malloc(reqlen);
4541 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004542 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004544 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004545 if (*args[4])
4546 reqlen += strlen(args[4]);
4547 else
4548 reqlen += strlen("HTTP/1.0");
4549
4550 curproxy->check_req = (char *)malloc(reqlen);
4551 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004552 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004553 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004554 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4555 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004556 }
4557 else if (!strcmp(args[1], "ssl-hello-chk")) {
4558 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004559 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004560 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004561
Willy Tarreaua534fea2008-08-03 12:19:50 +02004562 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004563 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004564 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004565 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004566
4567 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4568 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004569 }
Willy Tarreau23677902007-05-08 23:50:35 +02004570 else if (!strcmp(args[1], "smtpchk")) {
4571 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004572 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004573 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004574 curproxy->options2 &= ~PR_O2_CHK_ANY;
4575 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004576
4577 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4578 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4579 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4580 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4581 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4582 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4583 curproxy->check_req = (char *)malloc(reqlen);
4584 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4585 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4586 } else {
4587 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4588 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4589 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4590 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4591 }
4592 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004593 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4594 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004595 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004596 else if (!strcmp(args[1], "pgsql-check")) {
4597 /* use PostgreSQL request to check servers' health */
4598 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4599 err_code |= ERR_WARN;
4600
4601 free(curproxy->check_req);
4602 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004603 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004604 curproxy->options2 |= PR_O2_PGSQL_CHK;
4605
4606 if (*(args[2])) {
4607 int cur_arg = 2;
4608
4609 while (*(args[cur_arg])) {
4610 if (strcmp(args[cur_arg], "user") == 0) {
4611 char * packet;
4612 uint32_t packet_len;
4613 uint32_t pv;
4614
4615 /* suboption header - needs additional argument for it */
4616 if (*(args[cur_arg+1]) == 0) {
4617 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4618 file, linenum, args[0], args[1], args[cur_arg]);
4619 err_code |= ERR_ALERT | ERR_FATAL;
4620 goto out;
4621 }
4622
4623 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4624 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4625 pv = htonl(0x30000); /* protocol version 3.0 */
4626
4627 packet = (char*) calloc(1, packet_len);
4628
4629 memcpy(packet + 4, &pv, 4);
4630
4631 /* copy "user" */
4632 memcpy(packet + 8, "user", 4);
4633
4634 /* copy username */
4635 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4636
4637 free(curproxy->check_req);
4638 curproxy->check_req = packet;
4639 curproxy->check_len = packet_len;
4640
4641 packet_len = htonl(packet_len);
4642 memcpy(packet, &packet_len, 4);
4643 cur_arg += 2;
4644 } else {
4645 /* unknown suboption - catchall */
4646 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4647 file, linenum, args[0], args[1]);
4648 err_code |= ERR_ALERT | ERR_FATAL;
4649 goto out;
4650 }
4651 } /* end while loop */
4652 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004653 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4654 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004655 }
4656
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004657 else if (!strcmp(args[1], "redis-check")) {
4658 /* use REDIS PING request to check servers' health */
4659 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4660 err_code |= ERR_WARN;
4661
4662 free(curproxy->check_req);
4663 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004664 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004665 curproxy->options2 |= PR_O2_REDIS_CHK;
4666
4667 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4668 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4669 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004670
4671 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4672 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004673 }
4674
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004675 else if (!strcmp(args[1], "mysql-check")) {
4676 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004677 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4678 err_code |= ERR_WARN;
4679
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004680 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004681 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004682 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004683 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004684
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004685 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004686 * const char mysql40_client_auth_pkt[] = {
4687 * "\x0e\x00\x00" // packet length
4688 * "\x01" // packet number
4689 * "\x00\x00" // client capabilities
4690 * "\x00\x00\x01" // max packet
4691 * "haproxy\x00" // username (null terminated string)
4692 * "\x00" // filler (always 0x00)
4693 * "\x01\x00\x00" // packet length
4694 * "\x00" // packet number
4695 * "\x01" // COM_QUIT command
4696 * };
4697 */
4698
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004699 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4700 * const char mysql41_client_auth_pkt[] = {
4701 * "\x0e\x00\x00\" // packet length
4702 * "\x01" // packet number
4703 * "\x00\x00\x00\x00" // client capabilities
4704 * "\x00\x00\x00\x01" // max packet
4705 * "\x21" // character set (UTF-8)
4706 * char[23] // All zeroes
4707 * "haproxy\x00" // username (null terminated string)
4708 * "\x00" // filler (always 0x00)
4709 * "\x01\x00\x00" // packet length
4710 * "\x00" // packet number
4711 * "\x01" // COM_QUIT command
4712 * };
4713 */
4714
4715
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004716 if (*(args[2])) {
4717 int cur_arg = 2;
4718
4719 while (*(args[cur_arg])) {
4720 if (strcmp(args[cur_arg], "user") == 0) {
4721 char *mysqluser;
4722 int packetlen, reqlen, userlen;
4723
4724 /* suboption header - needs additional argument for it */
4725 if (*(args[cur_arg+1]) == 0) {
4726 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4727 file, linenum, args[0], args[1], args[cur_arg]);
4728 err_code |= ERR_ALERT | ERR_FATAL;
4729 goto out;
4730 }
4731 mysqluser = args[cur_arg + 1];
4732 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004733
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004734 if (*(args[cur_arg+2])) {
4735 if (!strcmp(args[cur_arg+2], "post-41")) {
4736 packetlen = userlen + 7 + 27;
4737 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004738
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004739 free(curproxy->check_req);
4740 curproxy->check_req = (char *)calloc(1, reqlen);
4741 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004742
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004743 snprintf(curproxy->check_req, 4, "%c%c%c",
4744 ((unsigned char) packetlen & 0xff),
4745 ((unsigned char) (packetlen >> 8) & 0xff),
4746 ((unsigned char) (packetlen >> 16) & 0xff));
4747
4748 curproxy->check_req[3] = 1;
4749 curproxy->check_req[5] = 130;
4750 curproxy->check_req[11] = 1;
4751 curproxy->check_req[12] = 33;
4752 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4753 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4754 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4755 cur_arg += 3;
4756 } else {
4757 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4758 err_code |= ERR_ALERT | ERR_FATAL;
4759 goto out;
4760 }
4761 } else {
4762 packetlen = userlen + 7;
4763 reqlen = packetlen + 9;
4764
4765 free(curproxy->check_req);
4766 curproxy->check_req = (char *)calloc(1, reqlen);
4767 curproxy->check_len = reqlen;
4768
4769 snprintf(curproxy->check_req, 4, "%c%c%c",
4770 ((unsigned char) packetlen & 0xff),
4771 ((unsigned char) (packetlen >> 8) & 0xff),
4772 ((unsigned char) (packetlen >> 16) & 0xff));
4773
4774 curproxy->check_req[3] = 1;
4775 curproxy->check_req[5] = 128;
4776 curproxy->check_req[8] = 1;
4777 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4778 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4779 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4780 cur_arg += 2;
4781 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004782 } else {
4783 /* unknown suboption - catchall */
4784 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4785 file, linenum, args[0], args[1]);
4786 err_code |= ERR_ALERT | ERR_FATAL;
4787 goto out;
4788 }
4789 } /* end while loop */
4790 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004791 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004792 else if (!strcmp(args[1], "ldap-check")) {
4793 /* use LDAP request to check servers' health */
4794 free(curproxy->check_req);
4795 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004796 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004797 curproxy->options2 |= PR_O2_LDAP_CHK;
4798
4799 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4800 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4801 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004802 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4803 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004804 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004805 else if (!strcmp(args[1], "tcp-check")) {
4806 /* use raw TCPCHK send/expect to check servers' health */
4807 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4808 err_code |= ERR_WARN;
4809
4810 free(curproxy->check_req);
4811 curproxy->check_req = NULL;
4812 curproxy->options2 &= ~PR_O2_CHK_ANY;
4813 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004814 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4815 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004816 }
Simon Horman98637e52014-06-20 12:30:16 +09004817 else if (!strcmp(args[1], "external-check")) {
4818 /* excute an external command to check servers' health */
4819 free(curproxy->check_req);
4820 curproxy->check_req = NULL;
4821 curproxy->options2 &= ~PR_O2_CHK_ANY;
4822 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004823 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4824 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004825 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004826 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004827 int cur_arg;
4828
4829 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4830 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004831 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004832
Willy Tarreau87cf5142011-08-19 22:57:24 +02004833 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004834
4835 free(curproxy->fwdfor_hdr_name);
4836 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4837 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4838
4839 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4840 cur_arg = 2;
4841 while (*(args[cur_arg])) {
4842 if (!strcmp(args[cur_arg], "except")) {
4843 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004844 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004845 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4846 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004847 err_code |= ERR_ALERT | ERR_FATAL;
4848 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004849 }
4850 /* flush useless bits */
4851 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004852 cur_arg += 2;
4853 } else if (!strcmp(args[cur_arg], "header")) {
4854 /* suboption header - needs additional argument for it */
4855 if (*(args[cur_arg+1]) == 0) {
4856 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4857 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004858 err_code |= ERR_ALERT | ERR_FATAL;
4859 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004860 }
4861 free(curproxy->fwdfor_hdr_name);
4862 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4863 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4864 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004865 } else if (!strcmp(args[cur_arg], "if-none")) {
4866 curproxy->options &= ~PR_O_FF_ALWAYS;
4867 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004868 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004869 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004870 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004871 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004872 err_code |= ERR_ALERT | ERR_FATAL;
4873 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004874 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004875 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004876 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004877 else if (!strcmp(args[1], "originalto")) {
4878 int cur_arg;
4879
4880 /* insert x-original-to field, but not for the IP address listed as an except.
4881 * set default options (ie: bitfield, header name, etc)
4882 */
4883
4884 curproxy->options |= PR_O_ORGTO;
4885
4886 free(curproxy->orgto_hdr_name);
4887 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4888 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4889
Willy Tarreau87cf5142011-08-19 22:57:24 +02004890 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004891 cur_arg = 2;
4892 while (*(args[cur_arg])) {
4893 if (!strcmp(args[cur_arg], "except")) {
4894 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004895 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 +02004896 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4897 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004898 err_code |= ERR_ALERT | ERR_FATAL;
4899 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004900 }
4901 /* flush useless bits */
4902 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4903 cur_arg += 2;
4904 } else if (!strcmp(args[cur_arg], "header")) {
4905 /* suboption header - needs additional argument for it */
4906 if (*(args[cur_arg+1]) == 0) {
4907 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4908 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004909 err_code |= ERR_ALERT | ERR_FATAL;
4910 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004911 }
4912 free(curproxy->orgto_hdr_name);
4913 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4914 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4915 cur_arg += 2;
4916 } else {
4917 /* unknown suboption - catchall */
4918 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4919 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004920 err_code |= ERR_ALERT | ERR_FATAL;
4921 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004922 }
4923 } /* end while loop */
4924 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004925 else {
4926 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004929 }
Willy Tarreau93893792009-07-23 13:19:11 +02004930 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004931 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004932 else if (!strcmp(args[0], "default_backend")) {
4933 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004934 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004935
4936 if (*(args[1]) == 0) {
4937 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004940 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004941 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004942 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02004943
4944 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4945 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004946 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004947 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004948 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004949 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004950
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004951 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4952 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 +01004953 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004954 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004955 /* enable reconnections to dispatch */
4956 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02004957
4958 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004960 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02004961 else if (!strcmp(args[0], "http-reuse")) {
4962 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4963 err_code |= ERR_WARN;
4964
4965 if (strcmp(args[1], "never") == 0) {
4966 /* enable a graceful server shutdown on an HTTP 404 response */
4967 curproxy->options &= ~PR_O_REUSE_MASK;
4968 curproxy->options |= PR_O_REUSE_NEVR;
4969 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4970 goto out;
4971 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02004972 else if (strcmp(args[1], "safe") == 0) {
4973 /* enable a graceful server shutdown on an HTTP 404 response */
4974 curproxy->options &= ~PR_O_REUSE_MASK;
4975 curproxy->options |= PR_O_REUSE_SAFE;
4976 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4977 goto out;
4978 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02004979 else if (strcmp(args[1], "aggressive") == 0) {
4980 curproxy->options &= ~PR_O_REUSE_MASK;
4981 curproxy->options |= PR_O_REUSE_AGGR;
4982 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4983 goto out;
4984 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02004985 else if (strcmp(args[1], "always") == 0) {
4986 /* enable a graceful server shutdown on an HTTP 404 response */
4987 curproxy->options &= ~PR_O_REUSE_MASK;
4988 curproxy->options |= PR_O_REUSE_ALWS;
4989 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4990 goto out;
4991 }
4992 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02004993 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02004994 err_code |= ERR_ALERT | ERR_FATAL;
4995 goto out;
4996 }
4997 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004998 else if (!strcmp(args[0], "http-check")) {
4999 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005001
5002 if (strcmp(args[1], "disable-on-404") == 0) {
5003 /* enable a graceful server shutdown on an HTTP 404 response */
5004 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005005 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5006 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005007 }
Willy Tarreauef781042010-01-27 11:53:01 +01005008 else if (strcmp(args[1], "send-state") == 0) {
5009 /* enable emission of the apparent state of a server in HTTP checks */
5010 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005011 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5012 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005013 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005014 else if (strcmp(args[1], "expect") == 0) {
5015 const char *ptr_arg;
5016 int cur_arg;
5017
5018 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5019 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5020 err_code |= ERR_ALERT | ERR_FATAL;
5021 goto out;
5022 }
5023
5024 cur_arg = 2;
5025 /* consider exclamation marks, sole or at the beginning of a word */
5026 while (*(ptr_arg = args[cur_arg])) {
5027 while (*ptr_arg == '!') {
5028 curproxy->options2 ^= PR_O2_EXP_INV;
5029 ptr_arg++;
5030 }
5031 if (*ptr_arg)
5032 break;
5033 cur_arg++;
5034 }
5035 /* now ptr_arg points to the beginning of a word past any possible
5036 * exclamation mark, and cur_arg is the argument which holds this word.
5037 */
5038 if (strcmp(ptr_arg, "status") == 0) {
5039 if (!*(args[cur_arg + 1])) {
5040 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5041 file, linenum, args[0], args[1], ptr_arg);
5042 err_code |= ERR_ALERT | ERR_FATAL;
5043 goto out;
5044 }
5045 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005046 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005047 curproxy->expect_str = strdup(args[cur_arg + 1]);
5048 }
5049 else if (strcmp(ptr_arg, "string") == 0) {
5050 if (!*(args[cur_arg + 1])) {
5051 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5052 file, linenum, args[0], args[1], ptr_arg);
5053 err_code |= ERR_ALERT | ERR_FATAL;
5054 goto out;
5055 }
5056 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005057 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005058 curproxy->expect_str = strdup(args[cur_arg + 1]);
5059 }
5060 else if (strcmp(ptr_arg, "rstatus") == 0) {
5061 if (!*(args[cur_arg + 1])) {
5062 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5063 file, linenum, args[0], args[1], ptr_arg);
5064 err_code |= ERR_ALERT | ERR_FATAL;
5065 goto out;
5066 }
5067 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005068 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005069 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005070 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005071 free(curproxy->expect_regex);
5072 curproxy->expect_regex = NULL;
5073 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005074 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005075 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5076 error = NULL;
5077 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5078 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5079 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5080 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005081 err_code |= ERR_ALERT | ERR_FATAL;
5082 goto out;
5083 }
5084 }
5085 else if (strcmp(ptr_arg, "rstring") == 0) {
5086 if (!*(args[cur_arg + 1])) {
5087 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5088 file, linenum, args[0], args[1], ptr_arg);
5089 err_code |= ERR_ALERT | ERR_FATAL;
5090 goto out;
5091 }
5092 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005093 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005094 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005095 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005096 free(curproxy->expect_regex);
5097 curproxy->expect_regex = NULL;
5098 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005099 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005100 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5101 error = NULL;
5102 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5103 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5104 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5105 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005106 err_code |= ERR_ALERT | ERR_FATAL;
5107 goto out;
5108 }
5109 }
5110 else {
5111 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5112 file, linenum, args[0], args[1], ptr_arg);
5113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
5115 }
5116 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005117 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005118 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 +02005119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005121 }
5122 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005123 else if (!strcmp(args[0], "tcp-check")) {
5124 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5125 err_code |= ERR_WARN;
5126
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005127 if (strcmp(args[1], "comment") == 0) {
5128 int cur_arg;
5129 struct tcpcheck_rule *tcpcheck;
5130
5131 cur_arg = 1;
5132 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5133 tcpcheck->action = TCPCHK_ACT_COMMENT;
5134
5135 if (!*args[cur_arg + 1]) {
5136 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5137 file, linenum, args[cur_arg]);
5138 err_code |= ERR_ALERT | ERR_FATAL;
5139 goto out;
5140 }
5141
5142 tcpcheck->comment = strdup(args[cur_arg + 1]);
5143
5144 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005145 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5146 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005147 }
5148 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005149 const char *ptr_arg;
5150 int cur_arg;
5151 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005152
5153 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005154 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5155 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5156 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5157 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5158 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005159
Willy Tarreau5581c272015-05-13 12:24:53 +02005160 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5161 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5162 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5163 file, linenum);
5164 err_code |= ERR_ALERT | ERR_FATAL;
5165 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005166 }
5167
5168 cur_arg = 2;
5169 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5170 tcpcheck->action = TCPCHK_ACT_CONNECT;
5171
5172 /* parsing each parameters to fill up the rule */
5173 while (*(ptr_arg = args[cur_arg])) {
5174 /* tcp port */
5175 if (strcmp(args[cur_arg], "port") == 0) {
5176 if ( (atol(args[cur_arg + 1]) > 65535) ||
5177 (atol(args[cur_arg + 1]) < 1) ){
5178 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5179 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5180 err_code |= ERR_ALERT | ERR_FATAL;
5181 goto out;
5182 }
5183 tcpcheck->port = atol(args[cur_arg + 1]);
5184 cur_arg += 2;
5185 }
5186 /* send proxy protocol */
5187 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5188 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5189 cur_arg++;
5190 }
5191#ifdef USE_OPENSSL
5192 else if (strcmp(args[cur_arg], "ssl") == 0) {
5193 curproxy->options |= PR_O_TCPCHK_SSL;
5194 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5195 cur_arg++;
5196 }
5197#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005198 /* comment for this tcpcheck line */
5199 else if (strcmp(args[cur_arg], "comment") == 0) {
5200 if (!*args[cur_arg + 1]) {
5201 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5202 file, linenum, args[cur_arg]);
5203 err_code |= ERR_ALERT | ERR_FATAL;
5204 goto out;
5205 }
5206 tcpcheck->comment = strdup(args[cur_arg + 1]);
5207 cur_arg += 2;
5208 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005209 else {
5210#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005211 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or 'ssl' but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005212#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005213 Alert("parsing [%s:%d] : '%s %s' expects 'comment', 'port', 'send-proxy' or but got '%s' as argument.\n",
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005214#endif /* USE_OPENSSL */
5215 file, linenum, args[0], args[1], args[cur_arg]);
5216 err_code |= ERR_ALERT | ERR_FATAL;
5217 goto out;
5218 }
5219
5220 }
5221
5222 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5223 }
5224 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005225 if (! *(args[2]) ) {
5226 /* SEND string expected */
5227 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5228 file, linenum, args[0], args[1], args[2]);
5229 err_code |= ERR_ALERT | ERR_FATAL;
5230 goto out;
5231 } else {
5232 struct tcpcheck_rule *tcpcheck;
5233
5234 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5235
5236 tcpcheck->action = TCPCHK_ACT_SEND;
5237 tcpcheck->string_len = strlen(args[2]);
5238 tcpcheck->string = strdup(args[2]);
5239 tcpcheck->expect_regex = NULL;
5240
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005241 /* comment for this tcpcheck line */
5242 if (strcmp(args[3], "comment") == 0) {
5243 if (!*args[4]) {
5244 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5245 file, linenum, args[3]);
5246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249 tcpcheck->comment = strdup(args[4]);
5250 }
5251
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005252 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5253 }
5254 }
5255 else if (strcmp(args[1], "send-binary") == 0) {
5256 if (! *(args[2]) ) {
5257 /* SEND binary string expected */
5258 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5259 file, linenum, args[0], args[1], args[2]);
5260 err_code |= ERR_ALERT | ERR_FATAL;
5261 goto out;
5262 } else {
5263 struct tcpcheck_rule *tcpcheck;
5264 char *err = NULL;
5265
5266 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5267
5268 tcpcheck->action = TCPCHK_ACT_SEND;
5269 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5270 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5271 file, linenum, args[0], args[1], args[2], err);
5272 err_code |= ERR_ALERT | ERR_FATAL;
5273 goto out;
5274 }
5275 tcpcheck->expect_regex = NULL;
5276
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005277 /* comment for this tcpcheck line */
5278 if (strcmp(args[3], "comment") == 0) {
5279 if (!*args[4]) {
5280 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5281 file, linenum, args[3]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285 tcpcheck->comment = strdup(args[4]);
5286 }
5287
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005288 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5289 }
5290 }
5291 else if (strcmp(args[1], "expect") == 0) {
5292 const char *ptr_arg;
5293 int cur_arg;
5294 int inverse = 0;
5295
5296 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5297 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5298 err_code |= ERR_ALERT | ERR_FATAL;
5299 goto out;
5300 }
5301
5302 cur_arg = 2;
5303 /* consider exclamation marks, sole or at the beginning of a word */
5304 while (*(ptr_arg = args[cur_arg])) {
5305 while (*ptr_arg == '!') {
5306 inverse = !inverse;
5307 ptr_arg++;
5308 }
5309 if (*ptr_arg)
5310 break;
5311 cur_arg++;
5312 }
5313 /* now ptr_arg points to the beginning of a word past any possible
5314 * exclamation mark, and cur_arg is the argument which holds this word.
5315 */
5316 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005317 struct tcpcheck_rule *tcpcheck;
5318 char *err = NULL;
5319
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005320 if (!*(args[cur_arg + 1])) {
5321 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5322 file, linenum, args[0], args[1], ptr_arg);
5323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
5325 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005326
5327 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5328
5329 tcpcheck->action = TCPCHK_ACT_EXPECT;
5330 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5331 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5332 file, linenum, args[0], args[1], args[2], err);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 tcpcheck->expect_regex = NULL;
5337 tcpcheck->inverse = inverse;
5338
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005339 /* tcpcheck comment */
5340 cur_arg += 2;
5341 if (strcmp(args[cur_arg], "comment") == 0) {
5342 if (!*args[cur_arg + 1]) {
5343 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5344 file, linenum, args[cur_arg + 1]);
5345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
5347 }
5348 tcpcheck->comment = strdup(args[cur_arg + 1]);
5349 }
5350
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005351 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5352 }
5353 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005354 struct tcpcheck_rule *tcpcheck;
5355
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005356 if (!*(args[cur_arg + 1])) {
5357 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5358 file, linenum, args[0], args[1], ptr_arg);
5359 err_code |= ERR_ALERT | ERR_FATAL;
5360 goto out;
5361 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005362
5363 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5364
5365 tcpcheck->action = TCPCHK_ACT_EXPECT;
5366 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5367 tcpcheck->string = strdup(args[cur_arg + 1]);
5368 tcpcheck->expect_regex = NULL;
5369 tcpcheck->inverse = inverse;
5370
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005371 /* tcpcheck comment */
5372 cur_arg += 2;
5373 if (strcmp(args[cur_arg], "comment") == 0) {
5374 if (!*args[cur_arg + 1]) {
5375 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5376 file, linenum, args[cur_arg + 1]);
5377 err_code |= ERR_ALERT | ERR_FATAL;
5378 goto out;
5379 }
5380 tcpcheck->comment = strdup(args[cur_arg + 1]);
5381 }
5382
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005383 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5384 }
5385 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005386 struct tcpcheck_rule *tcpcheck;
5387
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005388 if (!*(args[cur_arg + 1])) {
5389 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5390 file, linenum, args[0], args[1], ptr_arg);
5391 err_code |= ERR_ALERT | ERR_FATAL;
5392 goto out;
5393 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005394
5395 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5396
5397 tcpcheck->action = TCPCHK_ACT_EXPECT;
5398 tcpcheck->string_len = 0;
5399 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005400 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5401 error = NULL;
5402 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5403 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5404 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5405 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
5408 }
5409 tcpcheck->inverse = inverse;
5410
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005411 /* tcpcheck comment */
5412 cur_arg += 2;
5413 if (strcmp(args[cur_arg], "comment") == 0) {
5414 if (!*args[cur_arg + 1]) {
5415 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5416 file, linenum, args[cur_arg + 1]);
5417 err_code |= ERR_ALERT | ERR_FATAL;
5418 goto out;
5419 }
5420 tcpcheck->comment = strdup(args[cur_arg + 1]);
5421 }
5422
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005423 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5424 }
5425 else {
5426 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5427 file, linenum, args[0], args[1], ptr_arg);
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
5431 }
5432 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005433 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
5436 }
5437 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005438 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005439 if (curproxy == &defproxy) {
5440 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005441 err_code |= ERR_ALERT | ERR_FATAL;
5442 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005443 }
5444
Willy Tarreaub80c2302007-11-30 20:51:32 +01005445 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005446 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005447
5448 if (strcmp(args[1], "fail") == 0) {
5449 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005450 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005451 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5452 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005455 }
5456
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005457 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5458 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5459 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005460 err_code |= ERR_ALERT | ERR_FATAL;
5461 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005462 }
5463 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5464 }
5465 else {
5466 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005467 err_code |= ERR_ALERT | ERR_FATAL;
5468 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005469 }
5470 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005471#ifdef TPROXY
5472 else if (!strcmp(args[0], "transparent")) {
5473 /* enable transparent proxy connections */
5474 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005475 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 }
5478#endif
5479 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005480 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005481 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005482
Willy Tarreaubaaee002006-06-26 02:48:02 +02005483 if (*(args[1]) == 0) {
5484 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005487 }
5488 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005489 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005491 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005492 else if (!strcmp(args[0], "backlog")) { /* backlog */
5493 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005494 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005495
5496 if (*(args[1]) == 0) {
5497 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005500 }
5501 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005502 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5503 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005504 }
Willy Tarreau86034312006-12-29 00:10:33 +01005505 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005506 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005507 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005508
Willy Tarreau86034312006-12-29 00:10:33 +01005509 if (*(args[1]) == 0) {
5510 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005511 err_code |= ERR_ALERT | ERR_FATAL;
5512 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005513 }
5514 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005515 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5516 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005517 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005518 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5519 if (*(args[1]) == 0) {
5520 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005521 err_code |= ERR_ALERT | ERR_FATAL;
5522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005523 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005524 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5525 if (err) {
5526 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5527 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005528 err_code |= ERR_ALERT | ERR_FATAL;
5529 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005530 }
5531 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005532 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005534 }
5535 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005536 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005537 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005538 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005539
Willy Tarreaubaaee002006-06-26 02:48:02 +02005540 if (curproxy == &defproxy) {
5541 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005542 err_code |= ERR_ALERT | ERR_FATAL;
5543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005544 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005545 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005546 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005547
Willy Tarreau902636f2013-03-10 19:44:48 +01005548 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005549 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005550 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005551 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005552 goto out;
5553 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005554
5555 proto = protocol_by_family(sk->ss_family);
5556 if (!proto || !proto->connect) {
5557 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5558 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005559 err_code |= ERR_ALERT | ERR_FATAL;
5560 goto out;
5561 }
5562
5563 if (port1 != port2) {
5564 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5565 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005566 err_code |= ERR_ALERT | ERR_FATAL;
5567 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005568 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005569
5570 if (!port1) {
5571 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5572 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005573 err_code |= ERR_ALERT | ERR_FATAL;
5574 goto out;
5575 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005576
William Lallemanddf1425a2015-04-28 20:17:49 +02005577 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5578 goto out;
5579
Willy Tarreaud5191e72010-02-09 20:50:45 +01005580 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005581 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005582 }
5583 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005584 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005585 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005586
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005587 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5588 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005589 err_code |= ERR_ALERT | ERR_FATAL;
5590 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005591 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005592 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005593 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005594 /**
5595 * The syntax for hash-type config element is
5596 * hash-type {map-based|consistent} [[<algo>] avalanche]
5597 *
5598 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5599 */
5600 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005601
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005602 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5603 err_code |= ERR_WARN;
5604
5605 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005606 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5607 }
5608 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005609 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5610 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005611 else if (strcmp(args[1], "avalanche") == 0) {
5612 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]);
5613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005615 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005616 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005617 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005618 err_code |= ERR_ALERT | ERR_FATAL;
5619 goto out;
5620 }
Bhaskar98634f02013-10-29 23:30:51 -04005621
5622 /* set the hash function to use */
5623 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005624 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005625 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005626
5627 /* if consistent with no argument, then avalanche modifier is also applied */
5628 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5629 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005630 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005631 /* set the hash function */
5632 if (!strcmp(args[2], "sdbm")) {
5633 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5634 }
5635 else if (!strcmp(args[2], "djb2")) {
5636 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005637 }
5638 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005639 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005640 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005641 else if (!strcmp(args[2], "crc32")) {
5642 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5643 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005644 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005645 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 -05005646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
5649
5650 /* set the hash modifier */
5651 if (!strcmp(args[3], "avalanche")) {
5652 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5653 }
5654 else if (*args[3]) {
5655 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
5658 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005659 }
William Lallemanda73203e2012-03-12 12:48:57 +01005660 }
William Lallemanda73203e2012-03-12 12:48:57 +01005661 else if (strcmp(args[0], "unique-id-format") == 0) {
5662 if (!*(args[1])) {
5663 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5664 err_code |= ERR_ALERT | ERR_FATAL;
5665 goto out;
5666 }
William Lallemand3203ff42012-11-11 17:30:56 +01005667 if (*(args[2])) {
5668 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5669 err_code |= ERR_ALERT | ERR_FATAL;
5670 goto out;
5671 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005672 free(curproxy->conf.uniqueid_format_string);
5673 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005674
Willy Tarreau62a61232013-04-12 18:13:46 +02005675 free(curproxy->conf.uif_file);
5676 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5677 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005678 }
William Lallemanda73203e2012-03-12 12:48:57 +01005679
5680 else if (strcmp(args[0], "unique-id-header") == 0) {
5681 if (!*(args[1])) {
5682 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5683 err_code |= ERR_ALERT | ERR_FATAL;
5684 goto out;
5685 }
5686 free(curproxy->header_unique_id);
5687 curproxy->header_unique_id = strdup(args[1]);
5688 }
5689
William Lallemand723b73a2012-02-08 16:37:49 +01005690 else if (strcmp(args[0], "log-format") == 0) {
5691 if (!*(args[1])) {
5692 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5693 err_code |= ERR_ALERT | ERR_FATAL;
5694 goto out;
5695 }
William Lallemand3203ff42012-11-11 17:30:56 +01005696 if (*(args[2])) {
5697 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5698 err_code |= ERR_ALERT | ERR_FATAL;
5699 goto out;
5700 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005701
Willy Tarreau62a61232013-04-12 18:13:46 +02005702 if (curproxy->conf.logformat_string != default_http_log_format &&
5703 curproxy->conf.logformat_string != default_tcp_log_format &&
5704 curproxy->conf.logformat_string != clf_http_log_format)
5705 free(curproxy->conf.logformat_string);
5706 curproxy->conf.logformat_string = strdup(args[1]);
5707
5708 free(curproxy->conf.lfs_file);
5709 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5710 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005711
5712 /* get a chance to improve log-format error reporting by
5713 * reporting the correct line-number when possible.
5714 */
5715 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5716 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5717 file, linenum, curproxy->id);
5718 err_code |= ERR_WARN;
5719 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005720 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005721 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5722 if (*(args[1]) == 0) {
5723 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5724 err_code |= ERR_ALERT | ERR_FATAL;
5725 goto out;
5726 }
5727 free(curproxy->log_tag);
5728 curproxy->log_tag = strdup(args[1]);
5729 }
William Lallemand0f99e342011-10-12 17:50:54 +02005730 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5731 /* delete previous herited or defined syslog servers */
5732 struct logsrv *back;
5733
5734 if (*(args[1]) != 0) {
5735 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
5738 }
5739
William Lallemand723b73a2012-02-08 16:37:49 +01005740 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5741 LIST_DEL(&tmplogsrv->list);
5742 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005743 }
5744 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005745 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005746 struct logsrv *logsrv;
5747
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005749 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005750 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005751 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005752 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005753 LIST_INIT(&node->list);
5754 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5755 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 }
5757 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005758 struct sockaddr_storage *sk;
5759 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005760 int arg = 0;
5761 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005762
5763 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005764
Willy Tarreau18324f52014-06-27 18:10:07 +02005765 /* just after the address, a length may be specified */
5766 if (strcmp(args[arg+2], "len") == 0) {
5767 len = atoi(args[arg+3]);
5768 if (len < 80 || len > 65535) {
5769 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5770 file, linenum, args[arg+3]);
5771 err_code |= ERR_ALERT | ERR_FATAL;
5772 goto out;
5773 }
5774 logsrv->maxlen = len;
5775
5776 /* skip these two args */
5777 arg += 2;
5778 }
5779 else
5780 logsrv->maxlen = MAX_SYSLOG_LEN;
5781
5782 if (logsrv->maxlen > global.max_syslog_len) {
5783 global.max_syslog_len = logsrv->maxlen;
5784 logline = realloc(logline, global.max_syslog_len + 1);
5785 }
5786
William Lallemanddf1425a2015-04-28 20:17:49 +02005787 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5788 goto out;
5789
Willy Tarreau18324f52014-06-27 18:10:07 +02005790 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005791 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005792 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
5795
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 }
5797
William Lallemand0f99e342011-10-12 17:50:54 +02005798 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005799 if (*(args[arg+3])) {
5800 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005801 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005802 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005803 err_code |= ERR_ALERT | ERR_FATAL;
5804 goto out;
5805
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 }
5807 }
5808
William Lallemand0f99e342011-10-12 17:50:54 +02005809 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005810 if (*(args[arg+4])) {
5811 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005812 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005813 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005814 err_code |= ERR_ALERT | ERR_FATAL;
5815 goto out;
5816
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005817 }
5818 }
5819
Willy Tarreau902636f2013-03-10 19:44:48 +01005820 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005821 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005822 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005823 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005824 goto out;
5825 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005826
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005827 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005828
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005829 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005830 if (port1 != port2) {
5831 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5832 file, linenum, args[0], args[1]);
5833 err_code |= ERR_ALERT | ERR_FATAL;
5834 goto out;
5835 }
5836
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005837 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005838 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005839 }
William Lallemand0f99e342011-10-12 17:50:54 +02005840
5841 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005842 }
5843 else {
5844 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5845 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005846 err_code |= ERR_ALERT | ERR_FATAL;
5847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005848 }
5849 }
5850 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005851 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005852 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005853 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005854 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005855
Willy Tarreau977b8e42006-12-29 14:19:17 +01005856 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005857 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005858
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005860 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5861 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005864 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005865
5866 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005867 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5868 free(curproxy->conn_src.iface_name);
5869 curproxy->conn_src.iface_name = NULL;
5870 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005871
Willy Tarreau902636f2013-03-10 19:44:48 +01005872 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005873 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005874 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005875 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005876 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005877 goto out;
5878 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005879
5880 proto = protocol_by_family(sk->ss_family);
5881 if (!proto || !proto->connect) {
5882 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005883 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005884 err_code |= ERR_ALERT | ERR_FATAL;
5885 goto out;
5886 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005887
5888 if (port1 != port2) {
5889 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5890 file, linenum, args[0], args[1]);
5891 err_code |= ERR_ALERT | ERR_FATAL;
5892 goto out;
5893 }
5894
Willy Tarreauef9a3602012-12-08 22:29:20 +01005895 curproxy->conn_src.source_addr = *sk;
5896 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005897
5898 cur_arg = 2;
5899 while (*(args[cur_arg])) {
5900 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02005901#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005902 if (!*args[cur_arg + 1]) {
5903 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5904 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005905 err_code |= ERR_ALERT | ERR_FATAL;
5906 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005907 }
5908
5909 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005910 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5911 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005912 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005913 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5914 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005915 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5916 char *name, *end;
5917
5918 name = args[cur_arg+1] + 7;
5919 while (isspace(*name))
5920 name++;
5921
5922 end = name;
5923 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5924 end++;
5925
Willy Tarreauef9a3602012-12-08 22:29:20 +01005926 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5927 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5928 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5929 curproxy->conn_src.bind_hdr_len = end - name;
5930 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5931 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5932 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005933
5934 /* now look for an occurrence number */
5935 while (isspace(*end))
5936 end++;
5937 if (*end == ',') {
5938 end++;
5939 name = end;
5940 if (*end == '-')
5941 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005942 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005943 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005944 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005945 }
5946
Willy Tarreauef9a3602012-12-08 22:29:20 +01005947 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005948 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5949 " occurrences values smaller than %d.\n",
5950 file, linenum, MAX_HDR_HISTORY);
5951 err_code |= ERR_ALERT | ERR_FATAL;
5952 goto out;
5953 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005954 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005955 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005956
Willy Tarreau902636f2013-03-10 19:44:48 +01005957 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005958 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005959 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005960 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005961 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005962 goto out;
5963 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005964
5965 proto = protocol_by_family(sk->ss_family);
5966 if (!proto || !proto->connect) {
5967 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5968 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005972
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005973 if (port1 != port2) {
5974 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5975 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005976 err_code |= ERR_ALERT | ERR_FATAL;
5977 goto out;
5978 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005979 curproxy->conn_src.tproxy_addr = *sk;
5980 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005981 }
5982 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005983#else /* no TPROXY support */
5984 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005985 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005986 err_code |= ERR_ALERT | ERR_FATAL;
5987 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005988#endif
5989 cur_arg += 2;
5990 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005991 }
5992
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005993 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5994#ifdef SO_BINDTODEVICE
5995 if (!*args[cur_arg + 1]) {
5996 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5997 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006000 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006001 free(curproxy->conn_src.iface_name);
6002 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6003 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006004 global.last_checks |= LSTCHK_NETADM;
6005#else
6006 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6007 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006008 err_code |= ERR_ALERT | ERR_FATAL;
6009 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006010#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006011 cur_arg += 2;
6012 continue;
6013 }
6014 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006015 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006016 err_code |= ERR_ALERT | ERR_FATAL;
6017 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006018 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006019 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006020 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6021 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6022 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006023 err_code |= ERR_ALERT | ERR_FATAL;
6024 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006026 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006027 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006028 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6029 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006030 err_code |= ERR_ALERT | ERR_FATAL;
6031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006032 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006033
6034 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006035 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006036 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006037 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006039 }
6040 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006041 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006042 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006043 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006044 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006046 }
6047 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006048 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006049 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006050 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006051 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006053 }
6054 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006055 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006056 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006057 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006058 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006059 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 }
6061 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006062 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006063 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006064 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006065 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006068 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006069 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006070 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006071 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006072 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006073 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006074 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006075 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006076 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006077 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6078 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006079 err_code |= ERR_ALERT | ERR_FATAL;
6080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006082
6083 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006084 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006085 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006086 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006088 }
6089 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006090 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006091 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006092 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006093 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006095 }
6096 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006097 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006098 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006099 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006100 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102 }
6103 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006104 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006105 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006106 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006107 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006109 }
6110 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006111 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006112 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006113 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006114 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006116 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006117 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006118 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006119 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006120 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006121 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006122 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006123 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006125 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006126
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127 if (curproxy == &defproxy) {
6128 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006129 err_code |= ERR_ALERT | ERR_FATAL;
6130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006131 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006132 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006133 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006134
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 if (*(args[1]) == 0) {
6136 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006137 err_code |= ERR_ALERT | ERR_FATAL;
6138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006139 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006140
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006141 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006142 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6143 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6144 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006145 err_code |= ERR_ALERT | ERR_FATAL;
6146 goto out;
6147 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006148 err_code |= warnif_cond_conflicts(cond,
6149 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6150 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006151 }
6152 else if (*args[2]) {
6153 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6154 file, linenum, args[0], args[2]);
6155 err_code |= ERR_ALERT | ERR_FATAL;
6156 goto out;
6157 }
6158
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006159 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006160 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006161 wl->s = strdup(args[1]);
6162 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006163 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006164 }
6165 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006166 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006167 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006169 err_code |= ERR_ALERT | ERR_FATAL;
6170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006171 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006172
Willy Tarreauade5ec42010-01-28 19:33:49 +01006173 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006174 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006175 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006176 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 }
6179 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006180 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006181 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006182 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006183 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006184 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006185 }
6186 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006187 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006188 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006189 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006190 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006191 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006192 }
6193 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006194 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006195 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6196 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006197 err_code |= ERR_ALERT | ERR_FATAL;
6198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006199 }
6200
Willy Tarreauade5ec42010-01-28 19:33:49 +01006201 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006202 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006203 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006204 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006206 }
6207 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006208 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006209 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006210 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006211 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006213 }
6214 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006215 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006216 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006217 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006218 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006219 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006220 }
6221 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006222 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006223
Willy Tarreaubaaee002006-06-26 02:48:02 +02006224 if (curproxy == &defproxy) {
6225 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006226 err_code |= ERR_ALERT | ERR_FATAL;
6227 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006228 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006229 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006230 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006231
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 if (*(args[1]) == 0) {
6233 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006234 err_code |= ERR_ALERT | ERR_FATAL;
6235 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006236 }
6237
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006238 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006239 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6240 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6241 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006242 err_code |= ERR_ALERT | ERR_FATAL;
6243 goto out;
6244 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006245 err_code |= warnif_cond_conflicts(cond,
6246 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6247 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006248 }
6249 else if (*args[2]) {
6250 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6251 file, linenum, args[0], args[2]);
6252 err_code |= ERR_ALERT | ERR_FATAL;
6253 goto out;
6254 }
6255
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006256 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006257 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006258 wl->s = strdup(args[1]);
6259 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
6261 else if (!strcmp(args[0], "errorloc") ||
6262 !strcmp(args[0], "errorloc302") ||
6263 !strcmp(args[0], "errorloc303")) { /* error location */
6264 int errnum, errlen;
6265 char *err;
6266
Willy Tarreau977b8e42006-12-29 14:19:17 +01006267 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006268 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006269
Willy Tarreaubaaee002006-06-26 02:48:02 +02006270 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006271 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006272 err_code |= ERR_ALERT | ERR_FATAL;
6273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006274 }
6275
6276 errnum = atol(args[1]);
6277 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006278 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6279 err = malloc(errlen);
6280 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006281 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006282 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6283 err = malloc(errlen);
6284 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006285 }
6286
Willy Tarreau0f772532006-12-23 20:51:41 +01006287 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6288 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006289 chunk_destroy(&curproxy->errmsg[rc]);
6290 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006291 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006293 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006294
6295 if (rc >= HTTP_ERR_SIZE) {
6296 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6297 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006298 free(err);
6299 }
6300 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006301 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6302 int errnum, errlen, fd;
6303 char *err;
6304 struct stat stat;
6305
6306 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006307 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006308
6309 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006310 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006311 err_code |= ERR_ALERT | ERR_FATAL;
6312 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006313 }
6314
6315 fd = open(args[2], O_RDONLY);
6316 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6317 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6318 file, linenum, args[2], args[1]);
6319 if (fd >= 0)
6320 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006321 err_code |= ERR_ALERT | ERR_FATAL;
6322 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006323 }
6324
Willy Tarreau27a674e2009-08-17 07:23:33 +02006325 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006326 errlen = stat.st_size;
6327 } else {
6328 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006329 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006330 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006331 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006332 }
6333
6334 err = malloc(errlen); /* malloc() must succeed during parsing */
6335 errnum = read(fd, err, errlen);
6336 if (errnum != errlen) {
6337 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6338 file, linenum, args[2], args[1]);
6339 close(fd);
6340 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006341 err_code |= ERR_ALERT | ERR_FATAL;
6342 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006343 }
6344 close(fd);
6345
6346 errnum = atol(args[1]);
6347 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6348 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006349 chunk_destroy(&curproxy->errmsg[rc]);
6350 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006351 break;
6352 }
6353 }
6354
6355 if (rc >= HTTP_ERR_SIZE) {
6356 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6357 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006358 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006359 free(err);
6360 }
6361 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006362 else if (!strcmp(args[0], "compression")) {
6363 struct comp *comp;
6364 if (curproxy->comp == NULL) {
6365 comp = calloc(1, sizeof(struct comp));
6366 curproxy->comp = comp;
6367 } else {
6368 comp = curproxy->comp;
6369 }
6370
6371 if (!strcmp(args[1], "algo")) {
6372 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006373 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006374
William Lallemand82fe75c2012-10-23 10:25:10 +02006375 cur_arg = 2;
6376 if (!*args[cur_arg]) {
6377 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6378 file, linenum, args[0]);
6379 err_code |= ERR_ALERT | ERR_FATAL;
6380 goto out;
6381 }
6382 while (*(args[cur_arg])) {
6383 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6384 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6385 file, linenum, args[0], args[cur_arg]);
6386 err_code |= ERR_ALERT | ERR_FATAL;
6387 goto out;
6388 }
William Lallemand552df672012-11-07 13:21:47 +01006389 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6390 curproxy->comp->algos->end(&ctx);
6391 } else {
6392 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6393 file, linenum, args[0], args[cur_arg]);
6394 err_code |= ERR_ALERT | ERR_FATAL;
6395 goto out;
6396 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006397 cur_arg ++;
6398 continue;
6399 }
6400 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006401 else if (!strcmp(args[1], "offload")) {
6402 comp->offload = 1;
6403 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006404 else if (!strcmp(args[1], "type")) {
6405 int cur_arg;
6406 cur_arg = 2;
6407 if (!*args[cur_arg]) {
6408 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6409 file, linenum, args[0]);
6410 err_code |= ERR_ALERT | ERR_FATAL;
6411 goto out;
6412 }
6413 while (*(args[cur_arg])) {
6414 comp_append_type(comp, args[cur_arg]);
6415 cur_arg ++;
6416 continue;
6417 }
6418 }
6419 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006420 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006421 file, linenum, args[0]);
6422 err_code |= ERR_ALERT | ERR_FATAL;
6423 goto out;
6424 }
6425 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006427 struct cfg_kw_list *kwl;
6428 int index;
6429
6430 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6431 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6432 if (kwl->kw[index].section != CFG_LISTEN)
6433 continue;
6434 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6435 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006436 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006437 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006438 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006439 err_code |= ERR_ALERT | ERR_FATAL;
6440 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006441 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006442 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006443 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006444 err_code |= ERR_WARN;
6445 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006446 }
Willy Tarreau93893792009-07-23 13:19:11 +02006447 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006448 }
6449 }
6450 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006451
Willy Tarreau6daf3432008-01-22 16:44:08 +01006452 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006453 err_code |= ERR_ALERT | ERR_FATAL;
6454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
Willy Tarreau93893792009-07-23 13:19:11 +02006456 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006457 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006458 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006459}
6460
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006461int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006462cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6463{
6464#ifdef CONFIG_HAP_NS
6465 const char *err;
6466 const char *item = args[0];
6467
6468 if (!strcmp(item, "namespace_list")) {
6469 return 0;
6470 }
6471 else if (!strcmp(item, "namespace")) {
6472 size_t idx = 1;
6473 const char *current;
6474 while (*(current = args[idx++])) {
6475 err = invalid_char(current);
6476 if (err) {
6477 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6478 file, linenum, *err, item, current);
6479 return ERR_ALERT | ERR_FATAL;
6480 }
6481
6482 if (netns_store_lookup(current, strlen(current))) {
6483 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6484 file, linenum, current);
6485 return ERR_ALERT | ERR_FATAL;
6486 }
6487 if (!netns_store_insert(current)) {
6488 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6489 file, linenum, current);
6490 return ERR_ALERT | ERR_FATAL;
6491 }
6492 }
6493 }
6494
6495 return 0;
6496#else
6497 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6498 file, linenum);
6499 return ERR_ALERT | ERR_FATAL;
6500#endif
6501}
6502
6503int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006504cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6505{
6506
6507 int err_code = 0;
6508 const char *err;
6509
6510 if (!strcmp(args[0], "userlist")) { /* new userlist */
6511 struct userlist *newul;
6512
6513 if (!*args[1]) {
6514 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6515 file, linenum, args[0]);
6516 err_code |= ERR_ALERT | ERR_FATAL;
6517 goto out;
6518 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006519 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6520 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006521
6522 err = invalid_char(args[1]);
6523 if (err) {
6524 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6525 file, linenum, *err, args[0], args[1]);
6526 err_code |= ERR_ALERT | ERR_FATAL;
6527 goto out;
6528 }
6529
6530 for (newul = userlist; newul; newul = newul->next)
6531 if (!strcmp(newul->name, args[1])) {
6532 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6533 file, linenum, args[1]);
6534 err_code |= ERR_WARN;
6535 goto out;
6536 }
6537
6538 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6539 if (!newul) {
6540 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6541 err_code |= ERR_ALERT | ERR_ABORT;
6542 goto out;
6543 }
6544
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006545 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006546 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006547 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6548 err_code |= ERR_ALERT | ERR_ABORT;
6549 goto out;
6550 }
6551
6552 newul->next = userlist;
6553 userlist = newul;
6554
6555 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006556 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006557 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006558 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006559
6560 if (!*args[1]) {
6561 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6562 file, linenum, args[0]);
6563 err_code |= ERR_ALERT | ERR_FATAL;
6564 goto out;
6565 }
6566
6567 err = invalid_char(args[1]);
6568 if (err) {
6569 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6570 file, linenum, *err, args[0], args[1]);
6571 err_code |= ERR_ALERT | ERR_FATAL;
6572 goto out;
6573 }
6574
William Lallemand4ac9f542015-05-28 18:03:51 +02006575 if (!userlist)
6576 goto out;
6577
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006578 for (ag = userlist->groups; ag; ag = ag->next)
6579 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006580 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6581 file, linenum, args[1], userlist->name);
6582 err_code |= ERR_ALERT;
6583 goto out;
6584 }
6585
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006586 ag = calloc(1, sizeof(*ag));
6587 if (!ag) {
6588 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6589 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006590 goto out;
6591 }
6592
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006593 ag->name = strdup(args[1]);
6594 if (!ag) {
6595 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6596 err_code |= ERR_ALERT | ERR_ABORT;
6597 goto out;
6598 }
6599
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006600 cur_arg = 2;
6601
6602 while (*args[cur_arg]) {
6603 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006604 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006605 cur_arg += 2;
6606 continue;
6607 } else {
6608 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6609 file, linenum, args[0]);
6610 err_code |= ERR_ALERT | ERR_FATAL;
6611 goto out;
6612 }
6613 }
6614
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006615 ag->next = userlist->groups;
6616 userlist->groups = ag;
6617
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006618 } else if (!strcmp(args[0], "user")) { /* new user */
6619 struct auth_users *newuser;
6620 int cur_arg;
6621
6622 if (!*args[1]) {
6623 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6624 file, linenum, args[0]);
6625 err_code |= ERR_ALERT | ERR_FATAL;
6626 goto out;
6627 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006628 if (!userlist)
6629 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006630
6631 for (newuser = userlist->users; newuser; newuser = newuser->next)
6632 if (!strcmp(newuser->user, args[1])) {
6633 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6634 file, linenum, args[1], userlist->name);
6635 err_code |= ERR_ALERT;
6636 goto out;
6637 }
6638
6639 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6640 if (!newuser) {
6641 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6642 err_code |= ERR_ALERT | ERR_ABORT;
6643 goto out;
6644 }
6645
6646 newuser->user = strdup(args[1]);
6647
6648 newuser->next = userlist->users;
6649 userlist->users = newuser;
6650
6651 cur_arg = 2;
6652
6653 while (*args[cur_arg]) {
6654 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006655#ifdef CONFIG_HAP_CRYPT
6656 if (!crypt("", args[cur_arg + 1])) {
6657 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6658 file, linenum, newuser->user);
6659 err_code |= ERR_ALERT | ERR_FATAL;
6660 goto out;
6661 }
6662#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006663 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6664 file, linenum);
6665 err_code |= ERR_ALERT;
6666#endif
6667 newuser->pass = strdup(args[cur_arg + 1]);
6668 cur_arg += 2;
6669 continue;
6670 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6671 newuser->pass = strdup(args[cur_arg + 1]);
6672 newuser->flags |= AU_O_INSECURE;
6673 cur_arg += 2;
6674 continue;
6675 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006676 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006677 cur_arg += 2;
6678 continue;
6679 } else {
6680 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6681 file, linenum, args[0]);
6682 err_code |= ERR_ALERT | ERR_FATAL;
6683 goto out;
6684 }
6685 }
6686 } else {
6687 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6688 err_code |= ERR_ALERT | ERR_FATAL;
6689 }
6690
6691out:
6692 return err_code;
6693}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006694
6695/*
6696 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006697 * Returns the error code, 0 if OK, or any combination of :
6698 * - ERR_ABORT: must abort ASAP
6699 * - ERR_FATAL: we can continue parsing but not start the service
6700 * - ERR_WARN: a warning has been emitted
6701 * - ERR_ALERT: an alert has been emitted
6702 * Only the two first ones can stop processing, the two others are just
6703 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006704 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006705int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006706{
William Lallemand64e84512015-05-12 14:25:37 +02006707 char *thisline;
6708 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006709 FILE *f;
6710 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006711 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006712 struct cfg_section *cs = NULL;
6713 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006714 int readbytes = 0;
6715
6716 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006717 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006718 return -1;
6719 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006720
6721 /* Register internal sections */
6722 if (!cfg_register_section("listen", cfg_parse_listen) ||
6723 !cfg_register_section("frontend", cfg_parse_listen) ||
6724 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006725 !cfg_register_section("defaults", cfg_parse_listen) ||
6726 !cfg_register_section("global", cfg_parse_global) ||
6727 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006728 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006729 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006730 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6731 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006732 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006733
Willy Tarreaubaaee002006-06-26 02:48:02 +02006734 if ((f=fopen(file,"r")) == NULL)
6735 return -1;
6736
William Lallemandb2f07452015-05-12 14:27:13 +02006737next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006738 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006739 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006740 char *end;
6741 char *args[MAX_LINE_ARGS + 1];
6742 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006743 int dquote = 0; /* double quote */
6744 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006745
Willy Tarreaubaaee002006-06-26 02:48:02 +02006746 linenum++;
6747
6748 end = line + strlen(line);
6749
William Lallemand64e84512015-05-12 14:25:37 +02006750 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006751 /* Check if we reached the limit and the last char is not \n.
6752 * Watch out for the last line without the terminating '\n'!
6753 */
William Lallemand64e84512015-05-12 14:25:37 +02006754 char *newline;
6755 int newlinesize = linesize * 2;
6756
6757 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6758 if (newline == NULL) {
6759 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6760 file, linenum);
6761 err_code |= ERR_ALERT | ERR_FATAL;
6762 continue;
6763 }
6764
6765 readbytes = linesize - 1;
6766 linesize = newlinesize;
6767 thisline = newline;
6768 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006769 }
6770
William Lallemand64e84512015-05-12 14:25:37 +02006771 readbytes = 0;
6772
Willy Tarreaubaaee002006-06-26 02:48:02 +02006773 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006774 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006775 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006776
Willy Tarreaubaaee002006-06-26 02:48:02 +02006777 arg = 0;
6778 args[arg] = line;
6779
6780 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006781 if (*line == '"' && !squote) { /* double quote outside single quotes */
6782 if (dquote)
6783 dquote = 0;
6784 else
6785 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006786 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006787 end--;
6788 }
6789 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6790 if (squote)
6791 squote = 0;
6792 else
6793 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006794 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006795 end--;
6796 }
6797 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006798 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6799 * C equivalent value. Other combinations left unchanged (eg: \1).
6800 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006801 int skip = 0;
6802 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6803 *line = line[1];
6804 skip = 1;
6805 }
6806 else if (line[1] == 'r') {
6807 *line = '\r';
6808 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006809 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006810 else if (line[1] == 'n') {
6811 *line = '\n';
6812 skip = 1;
6813 }
6814 else if (line[1] == 't') {
6815 *line = '\t';
6816 skip = 1;
6817 }
6818 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006819 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006820 unsigned char hex1, hex2;
6821 hex1 = toupper(line[2]) - '0';
6822 hex2 = toupper(line[3]) - '0';
6823 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6824 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6825 *line = (hex1<<4) + hex2;
6826 skip = 3;
6827 }
6828 else {
6829 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006830 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006831 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006832 } else if (line[1] == '"') {
6833 *line = '"';
6834 skip = 1;
6835 } else if (line[1] == '\'') {
6836 *line = '\'';
6837 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006838 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6839 *line = '$';
6840 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006841 }
6842 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006843 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006844 end -= skip;
6845 }
6846 line++;
6847 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006848 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006849 /* end of string, end of loop */
6850 *line = 0;
6851 break;
6852 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006853 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006854 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006855 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006856 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006857 line++;
6858 args[++arg] = line;
6859 }
William Lallemandb2f07452015-05-12 14:27:13 +02006860 else if (dquote && *line == '$') {
6861 /* environment variables are evaluated inside double quotes */
6862 char *var_beg;
6863 char *var_end;
6864 char save_char;
6865 char *value;
6866 int val_len;
6867 int newlinesize;
6868 int braces = 0;
6869
6870 var_beg = line + 1;
6871 var_end = var_beg;
6872
6873 if (*var_beg == '{') {
6874 var_beg++;
6875 var_end++;
6876 braces = 1;
6877 }
6878
6879 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6880 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6881 err_code |= ERR_ALERT | ERR_FATAL;
6882 goto next_line; /* skip current line */
6883 }
6884
6885 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6886 var_end++;
6887
6888 save_char = *var_end;
6889 *var_end = '\0';
6890 value = getenv(var_beg);
6891 *var_end = save_char;
6892 val_len = value ? strlen(value) : 0;
6893
6894 if (braces) {
6895 if (*var_end == '}') {
6896 var_end++;
6897 braces = 0;
6898 } else {
6899 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6900 err_code |= ERR_ALERT | ERR_FATAL;
6901 goto next_line; /* skip current line */
6902 }
6903 }
6904
6905 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6906
6907 /* if not enough space in thisline */
6908 if (newlinesize > linesize) {
6909 char *newline;
6910
6911 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6912 if (newline == NULL) {
6913 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6914 err_code |= ERR_ALERT | ERR_FATAL;
6915 goto next_line; /* slip current line */
6916 }
6917 /* recompute pointers if realloc returns a new pointer */
6918 if (newline != thisline) {
6919 int i;
6920 int diff;
6921
6922 for (i = 0; i <= arg; i++) {
6923 diff = args[i] - thisline;
6924 args[i] = newline + diff;
6925 }
6926
6927 diff = var_end - thisline;
6928 var_end = newline + diff;
6929 diff = end - thisline;
6930 end = newline + diff;
6931 diff = line - thisline;
6932 line = newline + diff;
6933 thisline = newline;
6934 }
6935 linesize = newlinesize;
6936 }
6937
6938 /* insert value inside the line */
6939 memmove(line + val_len, var_end, end - var_end + 1);
6940 memcpy(line, value, val_len);
6941 end += val_len - (var_end - line);
6942 line += val_len;
6943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006944 else {
6945 line++;
6946 }
6947 }
William Lallemandb2f07452015-05-12 14:27:13 +02006948
William Lallemandf9873ba2015-05-05 17:37:14 +02006949 if (dquote) {
6950 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6951 err_code |= ERR_ALERT | ERR_FATAL;
6952 }
6953
6954 if (squote) {
6955 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6956 err_code |= ERR_ALERT | ERR_FATAL;
6957 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006958
6959 /* empty line */
6960 if (!**args)
6961 continue;
6962
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006963 if (*line) {
6964 /* we had to stop due to too many args.
6965 * Let's terminate the string, print the offending part then cut the
6966 * last arg.
6967 */
6968 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6969 line++;
6970 *line = '\0';
6971
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006972 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006973 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006974 err_code |= ERR_ALERT | ERR_FATAL;
6975 args[arg] = line;
6976 }
6977
Willy Tarreau540abe42007-05-02 20:50:16 +02006978 /* zero out remaining args and ensure that at least one entry
6979 * is zeroed out.
6980 */
6981 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006982 args[arg] = line;
6983 }
6984
Willy Tarreau3842f002009-06-14 11:39:52 +02006985 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006986 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006987 char *tmp;
6988
Willy Tarreau3842f002009-06-14 11:39:52 +02006989 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006990 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006991 for (arg=0; *args[arg+1]; arg++)
6992 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006993 *tmp = '\0'; // fix the next arg to \0
6994 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006995 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006996 else if (!strcmp(args[0], "default")) {
6997 kwm = KWM_DEF;
6998 for (arg=0; *args[arg+1]; arg++)
6999 args[arg] = args[arg+1]; // shift args after inversion
7000 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007001
William Lallemand0f99e342011-10-12 17:50:54 +02007002 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7003 strcmp(args[0], "log") != 0) {
7004 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007005 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007006 }
7007
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007008 /* detect section start */
7009 list_for_each_entry(ics, &sections, list) {
7010 if (strcmp(args[0], ics->section_name) == 0) {
7011 cursection = ics->section_name;
7012 cs = ics;
7013 break;
7014 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007015 }
7016
Willy Tarreaubaaee002006-06-26 02:48:02 +02007017 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007018 if (cs)
7019 err_code |= cs->section_parser(file, linenum, args, kwm);
7020 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007021 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007022 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007023 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007024
7025 if (err_code & ERR_ABORT)
7026 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007027 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007028 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007029 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007030 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007031 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007032}
7033
Willy Tarreau64ab6072014-09-16 12:17:36 +02007034/* This function propagates processes from frontend <from> to backend <to> so
7035 * that it is always guaranteed that a backend pointed to by a frontend is
7036 * bound to all of its processes. After that, if the target is a "listen"
7037 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007038 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007039 * checked first to ensure that <to> is already bound to all processes of
7040 * <from>, there is no risk of looping and we ensure to follow the shortest
7041 * path to the destination.
7042 *
7043 * It is possible to set <to> to NULL for the first call so that the function
7044 * takes care of visiting the initial frontend in <from>.
7045 *
7046 * It is important to note that the function relies on the fact that all names
7047 * have already been resolved.
7048 */
7049void propagate_processes(struct proxy *from, struct proxy *to)
7050{
7051 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007052
7053 if (to) {
7054 /* check whether we need to go down */
7055 if (from->bind_proc &&
7056 (from->bind_proc & to->bind_proc) == from->bind_proc)
7057 return;
7058
7059 if (!from->bind_proc && !to->bind_proc)
7060 return;
7061
7062 to->bind_proc = from->bind_proc ?
7063 (to->bind_proc | from->bind_proc) : 0;
7064
7065 /* now propagate down */
7066 from = to;
7067 }
7068
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007069 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007070 return;
7071
Willy Tarreauf6b70012014-12-18 14:00:43 +01007072 if (from->state == PR_STSTOPPED)
7073 return;
7074
Willy Tarreau64ab6072014-09-16 12:17:36 +02007075 /* default_backend */
7076 if (from->defbe.be)
7077 propagate_processes(from, from->defbe.be);
7078
7079 /* use_backend */
7080 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007081 if (rule->dynamic)
7082 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007083 to = rule->be.backend;
7084 propagate_processes(from, to);
7085 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007086}
7087
Willy Tarreaubb925012009-07-23 13:36:36 +02007088/*
7089 * Returns the error code, 0 if OK, or any combination of :
7090 * - ERR_ABORT: must abort ASAP
7091 * - ERR_FATAL: we can continue parsing but not start the service
7092 * - ERR_WARN: a warning has been emitted
7093 * - ERR_ALERT: an alert has been emitted
7094 * Only the two first ones can stop processing, the two others are just
7095 * indicators.
7096 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007097int check_config_validity()
7098{
7099 int cfgerr = 0;
7100 struct proxy *curproxy = NULL;
7101 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007102 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007103 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007104 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007105
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007106 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007107 /*
7108 * Now, check for the integrity of all that we have collected.
7109 */
7110
7111 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007112 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007113
Willy Tarreau193b8c62012-11-22 00:17:38 +01007114 if (!global.tune.max_http_hdr)
7115 global.tune.max_http_hdr = MAX_HTTP_HDR;
7116
7117 if (!global.tune.cookie_len)
7118 global.tune.cookie_len = CAPTURE_LEN;
7119
7120 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7121
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007122 /* Post initialisation of the users and groups lists. */
7123 err_code = userlist_postinit();
7124 if (err_code != ERR_NONE)
7125 goto out;
7126
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007127 /* first, we will invert the proxy list order */
7128 curproxy = NULL;
7129 while (proxy) {
7130 struct proxy *next;
7131
7132 next = proxy->next;
7133 proxy->next = curproxy;
7134 curproxy = proxy;
7135 if (!next)
7136 break;
7137 proxy = next;
7138 }
7139
Willy Tarreau419ead82014-09-16 13:41:21 +02007140 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007141 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007142 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007143 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007144 struct act_rule *trule;
7145 struct act_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007146 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007147 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007148
Willy Tarreau050536d2012-10-04 08:47:34 +02007149 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007150 /* proxy ID not set, use automatic numbering with first
7151 * spare entry starting with next_pxid.
7152 */
7153 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7154 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7155 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007156 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007157 next_pxid++;
7158
Willy Tarreau55ea7572007-06-17 19:56:27 +02007159
Willy Tarreaubaaee002006-06-26 02:48:02 +02007160 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007161 /* ensure we don't keep listeners uselessly bound */
7162 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007163 free((void *)curproxy->table.peers.name);
7164 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007165 continue;
7166 }
7167
Willy Tarreau102df612014-05-07 23:56:38 +02007168 /* Check multi-process mode compatibility for the current proxy */
7169
7170 if (curproxy->bind_proc) {
7171 /* an explicit bind-process was specified, let's check how many
7172 * processes remain.
7173 */
David Carliere6c39412015-07-02 07:00:17 +00007174 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007175
7176 curproxy->bind_proc &= nbits(global.nbproc);
7177 if (!curproxy->bind_proc && nbproc == 1) {
7178 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);
7179 curproxy->bind_proc = 1;
7180 }
7181 else if (!curproxy->bind_proc && nbproc > 1) {
7182 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);
7183 curproxy->bind_proc = 0;
7184 }
7185 }
7186
Willy Tarreau3d209582014-05-09 17:06:11 +02007187 /* check and reduce the bind-proc of each listener */
7188 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7189 unsigned long mask;
7190
7191 if (!bind_conf->bind_proc)
7192 continue;
7193
7194 mask = nbits(global.nbproc);
7195 if (curproxy->bind_proc)
7196 mask &= curproxy->bind_proc;
7197 /* mask cannot be null here thanks to the previous checks */
7198
David Carliere6c39412015-07-02 07:00:17 +00007199 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007200 bind_conf->bind_proc &= mask;
7201
7202 if (!bind_conf->bind_proc && nbproc == 1) {
7203 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",
7204 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7205 bind_conf->bind_proc = mask & ~(mask - 1);
7206 }
7207 else if (!bind_conf->bind_proc && nbproc > 1) {
7208 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",
7209 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7210 bind_conf->bind_proc = 0;
7211 }
7212 }
7213
Willy Tarreauff01a212009-03-15 13:46:16 +01007214 switch (curproxy->mode) {
7215 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007216 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007217 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007218 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7219 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007220 cfgerr++;
7221 }
7222
7223 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007224 Warning("config : servers will be ignored for %s '%s'.\n",
7225 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007226 break;
7227
7228 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007229 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007230 break;
7231
7232 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007233 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007234 break;
7235 }
7236
Willy Tarreauf3934b82015-08-11 11:36:45 +02007237 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7238 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7239 proxy_type_str(curproxy), curproxy->id);
7240 err_code |= ERR_WARN;
7241 }
7242
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007243 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007244 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007245 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007246 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7247 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007248 cfgerr++;
7249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007250#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007251 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007252 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7253 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007254 cfgerr++;
7255 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007256#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007257 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007258 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7259 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007260 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007261 }
7262 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007263 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007264 /* If no LB algo is set in a backend, and we're not in
7265 * transparent mode, dispatch mode nor proxy mode, we
7266 * want to use balance roundrobin by default.
7267 */
7268 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7269 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007270 }
7271 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007272
Willy Tarreau1620ec32011-08-06 17:05:02 +02007273 if (curproxy->options & PR_O_DISPATCH)
7274 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7275 else if (curproxy->options & PR_O_HTTP_PROXY)
7276 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7277 else if (curproxy->options & PR_O_TRANSP)
7278 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007279
Willy Tarreau1620ec32011-08-06 17:05:02 +02007280 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7281 if (curproxy->options & PR_O_DISABLE404) {
7282 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7283 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7284 err_code |= ERR_WARN;
7285 curproxy->options &= ~PR_O_DISABLE404;
7286 }
7287 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7288 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7289 "send-state", proxy_type_str(curproxy), curproxy->id);
7290 err_code |= ERR_WARN;
7291 curproxy->options &= ~PR_O2_CHK_SNDST;
7292 }
Willy Tarreauef781042010-01-27 11:53:01 +01007293 }
7294
Simon Horman98637e52014-06-20 12:30:16 +09007295 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7296 if (!global.external_check) {
7297 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7298 curproxy->id, "option external-check");
7299 cfgerr++;
7300 }
7301 if (!curproxy->check_command) {
7302 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7303 curproxy->id, "option external-check");
7304 cfgerr++;
7305 }
7306 }
7307
Simon Horman64e34162015-02-06 11:11:57 +09007308 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007309 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7310 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007311 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7312 "'email-alert myhostname', or 'email-alert to' "
7313 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007314 "to be present).\n",
7315 proxy_type_str(curproxy), curproxy->id);
7316 err_code |= ERR_WARN;
7317 free_email_alert(curproxy);
7318 }
7319 if (!curproxy->email_alert.myhostname)
7320 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007321 }
7322
Simon Horman98637e52014-06-20 12:30:16 +09007323 if (curproxy->check_command) {
7324 int clear = 0;
7325 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7326 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7327 "external-check command", proxy_type_str(curproxy), curproxy->id);
7328 err_code |= ERR_WARN;
7329 clear = 1;
7330 }
7331 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7332 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7333 curproxy->id, "external-check command");
7334 cfgerr++;
7335 }
7336 if (clear) {
7337 free(curproxy->check_command);
7338 curproxy->check_command = NULL;
7339 }
7340 }
7341
7342 if (curproxy->check_path) {
7343 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7344 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7345 "external-check path", proxy_type_str(curproxy), curproxy->id);
7346 err_code |= ERR_WARN;
7347 free(curproxy->check_path);
7348 curproxy->check_path = NULL;
7349 }
7350 }
7351
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007352 /* if a default backend was specified, let's find it */
7353 if (curproxy->defbe.name) {
7354 struct proxy *target;
7355
Willy Tarreauafb39922015-05-26 12:04:09 +02007356 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007357 if (!target) {
7358 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7359 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007360 cfgerr++;
7361 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007362 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7363 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007364 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007365 } else if (target->mode != curproxy->mode &&
7366 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7367
7368 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7369 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7370 curproxy->conf.file, curproxy->conf.line,
7371 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7372 target->conf.file, target->conf.line);
7373 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007374 } else {
7375 free(curproxy->defbe.name);
7376 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007377
7378 /* Emit a warning if this proxy also has some servers */
7379 if (curproxy->srv) {
7380 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7381 curproxy->id);
7382 err_code |= ERR_WARN;
7383 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007384 }
7385 }
7386
Willy Tarreau55ea7572007-06-17 19:56:27 +02007387 /* find the target proxy for 'use_backend' rules */
7388 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007389 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007390 struct logformat_node *node;
7391 char *pxname;
7392
7393 /* Try to parse the string as a log format expression. If the result
7394 * of the parsing is only one entry containing a simple string, then
7395 * it's a standard string corresponding to a static rule, thus the
7396 * parsing is cancelled and be.name is restored to be resolved.
7397 */
7398 pxname = rule->be.name;
7399 LIST_INIT(&rule->be.expr);
7400 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7401 curproxy->conf.args.file, curproxy->conf.args.line);
7402 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7403
7404 if (!LIST_ISEMPTY(&rule->be.expr)) {
7405 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7406 rule->dynamic = 1;
7407 free(pxname);
7408 continue;
7409 }
7410 /* simple string: free the expression and fall back to static rule */
7411 free(node->arg);
7412 free(node);
7413 }
7414
7415 rule->dynamic = 0;
7416 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007417
Willy Tarreauafb39922015-05-26 12:04:09 +02007418 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007419 if (!target) {
7420 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7421 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007422 cfgerr++;
7423 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007424 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7425 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007426 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007427 } else if (target->mode != curproxy->mode &&
7428 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7429
7430 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7431 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7432 curproxy->conf.file, curproxy->conf.line,
7433 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7434 target->conf.file, target->conf.line);
7435 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007436 } else {
7437 free((void *)rule->be.name);
7438 rule->be.backend = target;
7439 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007440 }
7441
Willy Tarreau64ab6072014-09-16 12:17:36 +02007442 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007443 list_for_each_entry(srule, &curproxy->server_rules, list) {
7444 struct server *target = findserver(curproxy, srule->srv.name);
7445
7446 if (!target) {
7447 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7448 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7449 cfgerr++;
7450 continue;
7451 }
7452 free((void *)srule->srv.name);
7453 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007454 }
7455
Emeric Brunb982a3d2010-01-04 15:45:53 +01007456 /* find the target table for 'stick' rules */
7457 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7458 struct proxy *target;
7459
Emeric Brun1d33b292010-01-04 15:47:17 +01007460 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7461 if (mrule->flags & STK_IS_STORE)
7462 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7463
Emeric Brunb982a3d2010-01-04 15:45:53 +01007464 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007465 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007466 else
7467 target = curproxy;
7468
7469 if (!target) {
7470 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7471 curproxy->id, mrule->table.name);
7472 cfgerr++;
7473 }
7474 else if (target->table.size == 0) {
7475 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7476 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7477 cfgerr++;
7478 }
Willy Tarreau12785782012-04-27 21:37:17 +02007479 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7480 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007481 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7482 cfgerr++;
7483 }
7484 else {
7485 free((void *)mrule->table.name);
7486 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007487 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007488 }
7489 }
7490
7491 /* find the target table for 'store response' rules */
7492 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7493 struct proxy *target;
7494
Emeric Brun1d33b292010-01-04 15:47:17 +01007495 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7496
Emeric Brunb982a3d2010-01-04 15:45:53 +01007497 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007498 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007499 else
7500 target = curproxy;
7501
7502 if (!target) {
7503 Alert("Proxy '%s': unable to find store table '%s'.\n",
7504 curproxy->id, mrule->table.name);
7505 cfgerr++;
7506 }
7507 else if (target->table.size == 0) {
7508 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7509 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7510 cfgerr++;
7511 }
Willy Tarreau12785782012-04-27 21:37:17 +02007512 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7513 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007514 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7515 cfgerr++;
7516 }
7517 else {
7518 free((void *)mrule->table.name);
7519 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007520 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007521 }
7522 }
7523
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007524 /* find the target table for 'tcp-request' layer 4 rules */
7525 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7526 struct proxy *target;
7527
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007528 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007529 continue;
7530
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007531 if (trule->arg.trk_ctr.table.n)
7532 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007533 else
7534 target = curproxy;
7535
7536 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007537 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007538 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007539 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007540 cfgerr++;
7541 }
7542 else if (target->table.size == 0) {
7543 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007544 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007545 cfgerr++;
7546 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007547 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007548 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007549 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007550 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007551 cfgerr++;
7552 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007553 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007554 free(trule->arg.trk_ctr.table.n);
7555 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007556 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007557 * to pass a list of counters to track and allocate them right here using
7558 * stktable_alloc_data_type().
7559 */
7560 }
7561 }
7562
Willy Tarreaud1f96522010-08-03 19:34:32 +02007563 /* find the target table for 'tcp-request' layer 6 rules */
7564 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7565 struct proxy *target;
7566
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007567 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007568 continue;
7569
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007570 if (trule->arg.trk_ctr.table.n)
7571 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007572 else
7573 target = curproxy;
7574
7575 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007576 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007577 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007578 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007579 cfgerr++;
7580 }
7581 else if (target->table.size == 0) {
7582 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007583 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007584 cfgerr++;
7585 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007586 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007587 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007588 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007589 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007590 cfgerr++;
7591 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007592 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007593 free(trule->arg.trk_ctr.table.n);
7594 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007595 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007596 * to pass a list of counters to track and allocate them right here using
7597 * stktable_alloc_data_type().
7598 */
7599 }
7600 }
7601
Willy Tarreau09448f72014-06-25 18:12:15 +02007602 /* find the target table for 'http-request' layer 7 rules */
7603 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7604 struct proxy *target;
7605
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007606 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007607 continue;
7608
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007609 if (hrqrule->arg.trk_ctr.table.n)
7610 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007611 else
7612 target = curproxy;
7613
7614 if (!target) {
7615 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007616 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007617 http_req_trk_idx(hrqrule->action));
7618 cfgerr++;
7619 }
7620 else if (target->table.size == 0) {
7621 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007622 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007623 cfgerr++;
7624 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007625 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007626 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007627 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007628 http_req_trk_idx(hrqrule->action));
7629 cfgerr++;
7630 }
7631 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007632 free(hrqrule->arg.trk_ctr.table.n);
7633 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007634 /* Note: if we decide to enhance the track-sc syntax, we may be able
7635 * to pass a list of counters to track and allocate them right here using
7636 * stktable_alloc_data_type().
7637 */
7638 }
7639 }
7640
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007641 /* move any "block" rules at the beginning of the http-request rules */
7642 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7643 /* insert block_rules into http_req_rules at the beginning */
7644 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7645 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7646 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7647 curproxy->http_req_rules.n = curproxy->block_rules.n;
7648 LIST_INIT(&curproxy->block_rules);
7649 }
7650
Emeric Brun32da3c42010-09-23 18:39:19 +02007651 if (curproxy->table.peers.name) {
7652 struct peers *curpeers = peers;
7653
7654 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7655 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7656 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007657 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007658 break;
7659 }
7660 }
7661
7662 if (!curpeers) {
7663 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7664 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007665 free((void *)curproxy->table.peers.name);
7666 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007667 cfgerr++;
7668 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007669 else if (curpeers->state == PR_STSTOPPED) {
7670 /* silently disable this peers section */
7671 curproxy->table.peers.p = NULL;
7672 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007673 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007674 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7675 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007676 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007677 cfgerr++;
7678 }
7679 }
7680
Simon Horman9dc49962015-01-30 11:22:59 +09007681
7682 if (curproxy->email_alert.mailers.name) {
7683 struct mailers *curmailers = mailers;
7684
7685 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7686 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7687 free(curproxy->email_alert.mailers.name);
7688 curproxy->email_alert.mailers.m = curmailers;
7689 curmailers->users++;
7690 break;
7691 }
7692 }
7693
7694 if (!curmailers) {
7695 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7696 curproxy->id, curproxy->email_alert.mailers.name);
7697 free_email_alert(curproxy);
7698 cfgerr++;
7699 }
7700 }
7701
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007702 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007703 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007704 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7705 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7706 "proxy", curproxy->id);
7707 cfgerr++;
7708 goto out_uri_auth_compat;
7709 }
7710
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007711 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007712 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007713 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007714 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007715
Willy Tarreau95fa4692010-02-01 13:05:50 +01007716 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7717 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007718
7719 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007720 uri_auth_compat_req[i++] = "realm";
7721 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7722 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007723
Willy Tarreau95fa4692010-02-01 13:05:50 +01007724 uri_auth_compat_req[i++] = "unless";
7725 uri_auth_compat_req[i++] = "{";
7726 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7727 uri_auth_compat_req[i++] = "}";
7728 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007729
Willy Tarreauff011f22011-01-06 17:51:27 +01007730 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7731 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007732 cfgerr++;
7733 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007734 }
7735
Willy Tarreauff011f22011-01-06 17:51:27 +01007736 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007737
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007738 if (curproxy->uri_auth->auth_realm) {
7739 free(curproxy->uri_auth->auth_realm);
7740 curproxy->uri_auth->auth_realm = NULL;
7741 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007742
7743 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007744 }
7745out_uri_auth_compat:
7746
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007747 /* compile the log format */
7748 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007749 if (curproxy->conf.logformat_string != default_http_log_format &&
7750 curproxy->conf.logformat_string != default_tcp_log_format &&
7751 curproxy->conf.logformat_string != clf_http_log_format)
7752 free(curproxy->conf.logformat_string);
7753 curproxy->conf.logformat_string = NULL;
7754 free(curproxy->conf.lfs_file);
7755 curproxy->conf.lfs_file = NULL;
7756 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007757 }
7758
Willy Tarreau62a61232013-04-12 18:13:46 +02007759 if (curproxy->conf.logformat_string) {
7760 curproxy->conf.args.ctx = ARGC_LOG;
7761 curproxy->conf.args.file = curproxy->conf.lfs_file;
7762 curproxy->conf.args.line = curproxy->conf.lfs_line;
7763 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007764 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007765 curproxy->conf.args.file = NULL;
7766 curproxy->conf.args.line = 0;
7767 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007768
Willy Tarreau62a61232013-04-12 18:13:46 +02007769 if (curproxy->conf.uniqueid_format_string) {
7770 curproxy->conf.args.ctx = ARGC_UIF;
7771 curproxy->conf.args.file = curproxy->conf.uif_file;
7772 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007773 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007774 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007775 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007776 curproxy->conf.args.file = NULL;
7777 curproxy->conf.args.line = 0;
7778 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007779
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007780 /* only now we can check if some args remain unresolved.
7781 * This must be done after the users and groups resolution.
7782 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007783 cfgerr += smp_resolve_args(curproxy);
7784 if (!cfgerr)
7785 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007786
Willy Tarreau2738a142006-07-08 17:28:09 +02007787 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007788 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007789 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007790 (!curproxy->timeout.connect ||
7791 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007792 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007793 " | While not properly invalid, you will certainly encounter various problems\n"
7794 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007795 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007796 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007797 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007798 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007799
Willy Tarreau1fa31262007-12-03 00:36:16 +01007800 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7801 * We must still support older configurations, so let's find out whether those
7802 * parameters have been set or must be copied from contimeouts.
7803 */
7804 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007805 if (!curproxy->timeout.tarpit ||
7806 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007807 /* tarpit timeout not set. We search in the following order:
7808 * default.tarpit, curr.connect, default.connect.
7809 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007810 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007811 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007812 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007813 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007814 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007815 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007816 }
7817 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007818 (!curproxy->timeout.queue ||
7819 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007820 /* queue timeout not set. We search in the following order:
7821 * default.queue, curr.connect, default.connect.
7822 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007823 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007824 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007825 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007826 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007827 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007828 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007829 }
7830 }
7831
Willy Tarreau1620ec32011-08-06 17:05:02 +02007832 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007833 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7834 curproxy->check_req = (char *)malloc(curproxy->check_len);
7835 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007836 }
7837
Willy Tarreau215663d2014-06-13 18:30:23 +02007838 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7839 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7840 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7841 proxy_type_str(curproxy), curproxy->id);
7842 err_code |= ERR_WARN;
7843 }
7844
Willy Tarreau193b8c62012-11-22 00:17:38 +01007845 /* ensure that cookie capture length is not too large */
7846 if (curproxy->capture_len >= global.tune.cookie_len) {
7847 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7848 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7849 err_code |= ERR_WARN;
7850 curproxy->capture_len = global.tune.cookie_len - 1;
7851 }
7852
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007853 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007854 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007855 curproxy->req_cap_pool = create_pool("ptrcap",
7856 curproxy->nb_req_cap * sizeof(char *),
7857 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007858 }
7859
7860 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007861 curproxy->rsp_cap_pool = create_pool("ptrcap",
7862 curproxy->nb_rsp_cap * sizeof(char *),
7863 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007864 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007865
Willy Tarreaubaaee002006-06-26 02:48:02 +02007866 /* first, we will invert the servers list order */
7867 newsrv = NULL;
7868 while (curproxy->srv) {
7869 struct server *next;
7870
7871 next = curproxy->srv->next;
7872 curproxy->srv->next = newsrv;
7873 newsrv = curproxy->srv;
7874 if (!next)
7875 break;
7876 curproxy->srv = next;
7877 }
7878
Willy Tarreau17edc812014-01-03 12:14:34 +01007879 /* Check that no server name conflicts. This causes trouble in the stats.
7880 * We only emit a warning for the first conflict affecting each server,
7881 * in order to avoid combinatory explosion if all servers have the same
7882 * name. We do that only for servers which do not have an explicit ID,
7883 * because these IDs were made also for distinguishing them and we don't
7884 * want to annoy people who correctly manage them.
7885 */
7886 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7887 struct server *other_srv;
7888
7889 if (newsrv->puid)
7890 continue;
7891
7892 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7893 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7894 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7895 newsrv->conf.file, newsrv->conf.line,
7896 proxy_type_str(curproxy), curproxy->id,
7897 newsrv->id, other_srv->conf.line);
7898 break;
7899 }
7900 }
7901 }
7902
Willy Tarreaudd701652010-05-25 23:03:02 +02007903 /* assign automatic UIDs to servers which don't have one yet */
7904 next_id = 1;
7905 newsrv = curproxy->srv;
7906 while (newsrv != NULL) {
7907 if (!newsrv->puid) {
7908 /* server ID not set, use automatic numbering with first
7909 * spare entry starting with next_svid.
7910 */
7911 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7912 newsrv->conf.id.key = newsrv->puid = next_id;
7913 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7914 }
7915 next_id++;
7916 newsrv = newsrv->next;
7917 }
7918
Willy Tarreau20697042007-11-15 23:26:18 +01007919 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007920 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007921
Willy Tarreau62c3be22012-01-20 13:12:32 +01007922 /*
7923 * If this server supports a maxconn parameter, it needs a dedicated
7924 * tasks to fill the emptied slots when a connection leaves.
7925 * Also, resolve deferred tracking dependency if needed.
7926 */
7927 newsrv = curproxy->srv;
7928 while (newsrv != NULL) {
7929 if (newsrv->minconn > newsrv->maxconn) {
7930 /* Only 'minconn' was specified, or it was higher than or equal
7931 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7932 * this will avoid further useless expensive computations.
7933 */
7934 newsrv->maxconn = newsrv->minconn;
7935 } else if (newsrv->maxconn && !newsrv->minconn) {
7936 /* minconn was not specified, so we set it to maxconn */
7937 newsrv->minconn = newsrv->maxconn;
7938 }
7939
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007940#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007941 if (newsrv->use_ssl || newsrv->check.use_ssl)
7942 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007943#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007944
Willy Tarreau2f075e92013-12-03 11:11:34 +01007945 /* set the check type on the server */
7946 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7947
Willy Tarreau62c3be22012-01-20 13:12:32 +01007948 if (newsrv->trackit) {
7949 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007950 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007951 char *pname, *sname;
7952
7953 pname = newsrv->trackit;
7954 sname = strrchr(pname, '/');
7955
7956 if (sname)
7957 *sname++ = '\0';
7958 else {
7959 sname = pname;
7960 pname = NULL;
7961 }
7962
7963 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007964 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007965 if (!px) {
7966 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7967 proxy_type_str(curproxy), curproxy->id,
7968 newsrv->id, pname);
7969 cfgerr++;
7970 goto next_srv;
7971 }
7972 } else
7973 px = curproxy;
7974
7975 srv = findserver(px, sname);
7976 if (!srv) {
7977 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7978 proxy_type_str(curproxy), curproxy->id,
7979 newsrv->id, sname);
7980 cfgerr++;
7981 goto next_srv;
7982 }
7983
Willy Tarreau32091232014-05-16 13:52:00 +02007984 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7985 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7986 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007987 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007988 "tracking as it does not have any check nor agent enabled.\n",
7989 proxy_type_str(curproxy), curproxy->id,
7990 newsrv->id, px->id, srv->id);
7991 cfgerr++;
7992 goto next_srv;
7993 }
7994
7995 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7996
7997 if (loop) {
7998 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7999 "belongs to a tracking chain looping back to %s/%s.\n",
8000 proxy_type_str(curproxy), curproxy->id,
8001 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008002 cfgerr++;
8003 goto next_srv;
8004 }
8005
8006 if (curproxy != px &&
8007 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8008 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8009 "tracking: disable-on-404 option inconsistency.\n",
8010 proxy_type_str(curproxy), curproxy->id,
8011 newsrv->id, px->id, srv->id);
8012 cfgerr++;
8013 goto next_srv;
8014 }
8015
8016 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008017 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008018 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008019 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008020 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008021 }
8022
8023 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008024 newsrv->tracknext = srv->trackers;
8025 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008026
8027 free(newsrv->trackit);
8028 newsrv->trackit = NULL;
8029 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008030
8031 /*
8032 * resolve server's resolvers name and update the resolvers pointer
8033 * accordingly
8034 */
8035 if (newsrv->resolvers_id) {
8036 struct dns_resolvers *curr_resolvers;
8037 int found;
8038
8039 found = 0;
8040 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8041 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8042 found = 1;
8043 break;
8044 }
8045 }
8046
8047 if (!found) {
8048 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8049 proxy_type_str(curproxy), curproxy->id,
8050 newsrv->id, newsrv->resolvers_id);
8051 cfgerr++;
8052 } else {
8053 free(newsrv->resolvers_id);
8054 newsrv->resolvers_id = NULL;
8055 if (newsrv->resolution)
8056 newsrv->resolution->resolvers = curr_resolvers;
8057 }
8058 }
8059 else {
8060 /* if no resolvers section associated to this server
8061 * we can clean up the associated resolution structure
8062 */
8063 if (newsrv->resolution) {
8064 free(newsrv->resolution->hostname_dn);
8065 newsrv->resolution->hostname_dn = NULL;
8066 free(newsrv->resolution);
8067 newsrv->resolution = NULL;
8068 }
8069 }
8070
Willy Tarreau62c3be22012-01-20 13:12:32 +01008071 next_srv:
8072 newsrv = newsrv->next;
8073 }
8074
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008075 /* We have to initialize the server lookup mechanism depending
8076 * on what LB algorithm was choosen.
8077 */
8078
8079 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8080 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8081 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008082 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8083 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8084 init_server_map(curproxy);
8085 } else {
8086 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8087 fwrr_init_server_groups(curproxy);
8088 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008089 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008090
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008091 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008092 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8093 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8094 fwlc_init_server_tree(curproxy);
8095 } else {
8096 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8097 fas_init_server_tree(curproxy);
8098 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008099 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008100
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008101 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008102 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8103 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8104 chash_init_server_tree(curproxy);
8105 } else {
8106 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8107 init_server_map(curproxy);
8108 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008109 break;
8110 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008111
8112 if (curproxy->options & PR_O_LOGASAP)
8113 curproxy->to_log &= ~LW_BYTES;
8114
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008115 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008116 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008117 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8118 proxy_type_str(curproxy), curproxy->id);
8119 err_code |= ERR_WARN;
8120 }
8121
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008122 if (curproxy->mode != PR_MODE_HTTP) {
8123 int optnum;
8124
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008125 if (curproxy->uri_auth) {
8126 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8127 proxy_type_str(curproxy), curproxy->id);
8128 err_code |= ERR_WARN;
8129 curproxy->uri_auth = NULL;
8130 }
8131
Willy Tarreau87cf5142011-08-19 22:57:24 +02008132 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008133 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8134 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8135 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008136 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008137 }
8138
8139 if (curproxy->options & PR_O_ORGTO) {
8140 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8141 "originalto", proxy_type_str(curproxy), curproxy->id);
8142 err_code |= ERR_WARN;
8143 curproxy->options &= ~PR_O_ORGTO;
8144 }
8145
8146 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8147 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8148 (curproxy->cap & cfg_opts[optnum].cap) &&
8149 (curproxy->options & cfg_opts[optnum].val)) {
8150 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8151 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8152 err_code |= ERR_WARN;
8153 curproxy->options &= ~cfg_opts[optnum].val;
8154 }
8155 }
8156
8157 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8158 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8159 (curproxy->cap & cfg_opts2[optnum].cap) &&
8160 (curproxy->options2 & cfg_opts2[optnum].val)) {
8161 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8162 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8163 err_code |= ERR_WARN;
8164 curproxy->options2 &= ~cfg_opts2[optnum].val;
8165 }
8166 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008167
Willy Tarreau29fbe512015-08-20 19:35:14 +02008168#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008169 if (curproxy->conn_src.bind_hdr_occ) {
8170 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008171 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008172 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008173 err_code |= ERR_WARN;
8174 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008175#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008176 }
8177
Willy Tarreaubaaee002006-06-26 02:48:02 +02008178 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008179 * ensure that we're not cross-dressing a TCP server into HTTP.
8180 */
8181 newsrv = curproxy->srv;
8182 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008183 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008184 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8185 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008186 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008187 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008188
Willy Tarreau0cec3312011-10-31 13:49:26 +01008189 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8190 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8191 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8192 err_code |= ERR_WARN;
8193 }
8194
Willy Tarreauc93cd162014-05-13 15:54:22 +02008195 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008196 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8197 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8198 err_code |= ERR_WARN;
8199 }
8200
Willy Tarreau29fbe512015-08-20 19:35:14 +02008201#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008202 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8203 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008204 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 +01008205 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008206 err_code |= ERR_WARN;
8207 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008208#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008209 newsrv = newsrv->next;
8210 }
8211
Willy Tarreaue42bd962014-09-16 16:21:19 +02008212 /* check if we have a frontend with "tcp-request content" looking at L7
8213 * with no inspect-delay
8214 */
8215 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8216 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008217 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008218 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008219 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008220 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008221 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008222 break;
8223 }
8224
8225 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8226 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8227 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8228 " This means that these rules will randomly find their contents. This can be fixed by"
8229 " setting the tcp-request inspect-delay.\n",
8230 proxy_type_str(curproxy), curproxy->id);
8231 err_code |= ERR_WARN;
8232 }
8233 }
8234
Willy Tarreauc1a21672009-08-16 22:37:44 +02008235 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008236 if (!curproxy->accept)
8237 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008238
Willy Tarreauc1a21672009-08-16 22:37:44 +02008239 if (curproxy->tcp_req.inspect_delay ||
8240 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008241 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008242
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008243 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008244 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008245 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008246 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008247
8248 /* both TCP and HTTP must check switching rules */
8249 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8250 }
8251
8252 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008253 if (curproxy->tcp_req.inspect_delay ||
8254 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8255 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8256
Emeric Brun97679e72010-09-23 17:56:44 +02008257 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8258 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8259
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008260 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008261 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008262 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008263 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008264
8265 /* If the backend does requires RDP cookie persistence, we have to
8266 * enable the corresponding analyser.
8267 */
8268 if (curproxy->options2 & PR_O2_RDPC_PRST)
8269 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8270 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008271 }
8272
8273 /***********************************************************/
8274 /* At this point, target names have already been resolved. */
8275 /***********************************************************/
8276
8277 /* Check multi-process mode compatibility */
8278
8279 if (global.nbproc > 1 && global.stats_fe) {
8280 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8281 unsigned long mask;
8282
8283 mask = nbits(global.nbproc);
8284 if (global.stats_fe->bind_proc)
8285 mask &= global.stats_fe->bind_proc;
8286
8287 if (bind_conf->bind_proc)
8288 mask &= bind_conf->bind_proc;
8289
8290 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008291 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008292 break;
8293 }
8294 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8295 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");
8296 }
8297 }
8298
8299 /* Make each frontend inherit bind-process from its listeners when not specified. */
8300 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8301 if (curproxy->bind_proc)
8302 continue;
8303
8304 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8305 unsigned long mask;
8306
Willy Tarreaue428b082015-05-04 21:57:58 +02008307 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008308 curproxy->bind_proc |= mask;
8309 }
8310
8311 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008312 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008313 }
8314
8315 if (global.stats_fe) {
8316 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8317 unsigned long mask;
8318
Willy Tarreaue428b082015-05-04 21:57:58 +02008319 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008320 global.stats_fe->bind_proc |= mask;
8321 }
8322 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008323 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008324 }
8325
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008326 /* propagate bindings from frontends to backends. Don't do it if there
8327 * are any fatal errors as we must not call it with unresolved proxies.
8328 */
8329 if (!cfgerr) {
8330 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8331 if (curproxy->cap & PR_CAP_FE)
8332 propagate_processes(curproxy, NULL);
8333 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008334 }
8335
8336 /* Bind each unbound backend to all processes when not specified. */
8337 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8338 if (curproxy->bind_proc)
8339 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008340 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008341 }
8342
8343 /*******************************************************/
8344 /* At this step, all proxies have a non-null bind_proc */
8345 /*******************************************************/
8346
8347 /* perform the final checks before creating tasks */
8348
8349 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8350 struct listener *listener;
8351 unsigned int next_id;
8352 int nbproc;
8353
David Carliere6c39412015-07-02 07:00:17 +00008354 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008355
Emeric Brunc52962f2012-11-15 18:28:02 +01008356#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008357 /* Configure SSL for each bind line.
8358 * Note: if configuration fails at some point, the ->ctx member
8359 * remains NULL so that listeners can later detach.
8360 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008361 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008362 int alloc_ctx;
8363
Emeric Brunc52962f2012-11-15 18:28:02 +01008364 if (!bind_conf->is_ssl) {
8365 if (bind_conf->default_ctx) {
8366 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8367 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8368 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008369 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008370 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008371 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008372 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008373 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008374 cfgerr++;
8375 continue;
8376 }
8377
Emeric Brun8dc60392014-05-09 13:52:00 +02008378 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008379 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008380 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8381 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");
8382 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008383 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008384 cfgerr++;
8385 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008386 }
8387
Emeric Brunfc0421f2012-09-07 17:30:07 +02008388 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008389 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008390
8391 /* initialize CA variables if the certificates generation is enabled */
8392 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008393 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008394#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008395
Willy Tarreaue6b98942007-10-29 01:09:36 +01008396 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008397 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008398 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008399 if (!listener->luid) {
8400 /* listener ID not set, use automatic numbering with first
8401 * spare entry starting with next_luid.
8402 */
8403 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8404 listener->conf.id.key = listener->luid = next_id;
8405 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008406 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008407 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008408
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008409 /* enable separate counters */
8410 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8411 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008412 if (!listener->name)
8413 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008414 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008415
Willy Tarreaue6b98942007-10-29 01:09:36 +01008416 if (curproxy->options & PR_O_TCP_NOLING)
8417 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008418 if (!listener->maxconn)
8419 listener->maxconn = curproxy->maxconn;
8420 if (!listener->backlog)
8421 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008422 if (!listener->maxaccept)
8423 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8424
8425 /* we want to have an optimal behaviour on single process mode to
8426 * maximize the work at once, but in multi-process we want to keep
8427 * some fairness between processes, so we target half of the max
8428 * number of events to be balanced over all the processes the proxy
8429 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8430 * used to disable the limit.
8431 */
8432 if (listener->maxaccept > 0) {
8433 if (nbproc > 1)
8434 listener->maxaccept = (listener->maxaccept + 1) / 2;
8435 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8436 }
8437
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008438 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008439 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008440 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008441 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008442
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008443 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8444 listener->options |= LI_O_TCP_RULES;
8445
Willy Tarreaude3041d2010-05-31 10:56:17 +02008446 if (curproxy->mon_mask.s_addr)
8447 listener->options |= LI_O_CHK_MONNET;
8448
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008449 /* smart accept mode is automatic in HTTP mode */
8450 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008451 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008452 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8453 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008454 }
8455
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008456 /* Release unused SSL configs */
8457 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8458 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008459 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008460#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008461 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008462 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008463 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008464 free(bind_conf->ca_sign_file);
8465 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008466 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008467 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008468 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008469 if(bind_conf->keys_ref) {
8470 free(bind_conf->keys_ref->filename);
8471 free(bind_conf->keys_ref->tlskeys);
8472 free(bind_conf->keys_ref);
8473 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008474#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008475 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008476
Willy Tarreau102df612014-05-07 23:56:38 +02008477 if (nbproc > 1) {
8478 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008479 int count, maxproc = 0;
8480
8481 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008482 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008483 if (count > maxproc)
8484 maxproc = count;
8485 }
8486 /* backends have 0, frontends have 1 or more */
8487 if (maxproc != 1)
8488 Warning("Proxy '%s': in multi-process mode, stats will be"
8489 " limited to process assigned to the current request.\n",
8490 curproxy->id);
8491
Willy Tarreau102df612014-05-07 23:56:38 +02008492 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8493 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8494 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008495 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008496 }
Willy Tarreau102df612014-05-07 23:56:38 +02008497 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8498 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8499 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008500 }
8501 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008502
8503 /* create the task associated with the proxy */
8504 curproxy->task = task_new();
8505 if (curproxy->task) {
8506 curproxy->task->context = curproxy;
8507 curproxy->task->process = manage_proxy;
8508 /* no need to queue, it will be done automatically if some
8509 * listener gets limited.
8510 */
8511 curproxy->task->expire = TICK_ETERNITY;
8512 } else {
8513 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8514 curproxy->id);
8515 cfgerr++;
8516 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008517 }
8518
Willy Tarreaufbb78422011-06-05 15:38:35 +02008519 /* automatically compute fullconn if not set. We must not do it in the
8520 * loop above because cross-references are not yet fully resolved.
8521 */
8522 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8523 /* If <fullconn> is not set, let's set it to 10% of the sum of
8524 * the possible incoming frontend's maxconns.
8525 */
8526 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8527 struct proxy *fe;
8528 int total = 0;
8529
8530 /* sum up the number of maxconns of frontends which
8531 * reference this backend at least once or which are
8532 * the same one ('listen').
8533 */
8534 for (fe = proxy; fe; fe = fe->next) {
8535 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008536 int found = 0;
8537
8538 if (!(fe->cap & PR_CAP_FE))
8539 continue;
8540
8541 if (fe == curproxy) /* we're on a "listen" instance */
8542 found = 1;
8543
8544 if (fe->defbe.be == curproxy) /* "default_backend" */
8545 found = 1;
8546
8547 /* check if a "use_backend" rule matches */
8548 if (!found) {
8549 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008550 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008551 found = 1;
8552 break;
8553 }
8554 }
8555 }
8556
Willy Tarreaufbb78422011-06-05 15:38:35 +02008557 /* now we've checked all possible ways to reference a backend
8558 * from a frontend.
8559 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008560 if (!found)
8561 continue;
8562 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008563 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008564 /* we have the sum of the maxconns in <total>. We only
8565 * keep 10% of that sum to set the default fullconn, with
8566 * a hard minimum of 1 (to avoid a divide by zero).
8567 */
8568 curproxy->fullconn = (total + 9) / 10;
8569 if (!curproxy->fullconn)
8570 curproxy->fullconn = 1;
8571 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008572 }
8573
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008574 /*
8575 * Recount currently required checks.
8576 */
8577
8578 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8579 int optnum;
8580
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008581 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8582 if (curproxy->options & cfg_opts[optnum].val)
8583 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008584
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008585 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8586 if (curproxy->options2 & cfg_opts2[optnum].val)
8587 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008588 }
8589
Willy Tarreau0fca4832015-05-01 19:12:05 +02008590 /* compute the required process bindings for the peers */
8591 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8592 if (curproxy->table.peers.p)
8593 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8594
Willy Tarreau122541c2011-09-07 21:24:49 +02008595 if (peers) {
8596 struct peers *curpeers = peers, **last;
8597 struct peer *p, *pb;
8598
Willy Tarreau1e273012015-05-01 19:15:17 +02008599 /* Remove all peers sections which don't have a valid listener,
8600 * which are not used by any table, or which are bound to more
8601 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008602 */
8603 last = &peers;
8604 while (*last) {
8605 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008606
8607 if (curpeers->state == PR_STSTOPPED) {
8608 /* the "disabled" keyword was present */
8609 if (curpeers->peers_fe)
8610 stop_proxy(curpeers->peers_fe);
8611 curpeers->peers_fe = NULL;
8612 }
8613 else if (!curpeers->peers_fe) {
8614 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8615 curpeers->id, localpeer);
8616 }
David Carliere6c39412015-07-02 07:00:17 +00008617 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008618 /* either it's totally stopped or too much used */
8619 if (curpeers->peers_fe->bind_proc) {
8620 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008621 "running in different processes (%d different ones). "
8622 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008623 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008624 cfgerr++;
8625 }
8626 stop_proxy(curpeers->peers_fe);
8627 curpeers->peers_fe = NULL;
8628 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008629 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008630 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008631 last = &curpeers->next;
8632 continue;
8633 }
8634
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008635 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008636 p = curpeers->remote;
8637 while (p) {
8638 pb = p->next;
8639 free(p->id);
8640 free(p);
8641 p = pb;
8642 }
8643
8644 /* Destroy and unlink this curpeers section.
8645 * Note: curpeers is backed up into *last.
8646 */
8647 free(curpeers->id);
8648 curpeers = curpeers->next;
8649 free(*last);
8650 *last = curpeers;
8651 }
8652 }
8653
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008654 /* initialize stick-tables on backend capable proxies. This must not
8655 * be done earlier because the data size may be discovered while parsing
8656 * other proxies.
8657 */
8658 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8659 if (curproxy->state == PR_STSTOPPED)
8660 continue;
8661
8662 if (!stktable_init(&curproxy->table)) {
8663 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8664 cfgerr++;
8665 }
8666 }
8667
Simon Horman0d16a402015-01-30 11:22:58 +09008668 if (mailers) {
8669 struct mailers *curmailers = mailers, **last;
8670 struct mailer *m, *mb;
8671
8672 /* Remove all mailers sections which don't have a valid listener.
8673 * This can happen when a mailers section is never referenced.
8674 */
8675 last = &mailers;
8676 while (*last) {
8677 curmailers = *last;
8678 if (curmailers->users) {
8679 last = &curmailers->next;
8680 continue;
8681 }
8682
8683 Warning("Removing incomplete section 'mailers %s'.\n",
8684 curmailers->id);
8685
8686 m = curmailers->mailer_list;
8687 while (m) {
8688 mb = m->next;
8689 free(m->id);
8690 free(m);
8691 m = mb;
8692 }
8693
8694 /* Destroy and unlink this curmailers section.
8695 * Note: curmailers is backed up into *last.
8696 */
8697 free(curmailers->id);
8698 curmailers = curmailers->next;
8699 free(*last);
8700 *last = curmailers;
8701 }
8702 }
8703
Willy Tarreau34eb6712011-10-24 18:15:04 +02008704 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008705 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008706 MEM_F_SHARED);
8707
Willy Tarreaubb925012009-07-23 13:36:36 +02008708 if (cfgerr > 0)
8709 err_code |= ERR_ALERT | ERR_FATAL;
8710 out:
8711 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008712}
8713
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008714/*
8715 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8716 * parsing sessions.
8717 */
8718void cfg_register_keywords(struct cfg_kw_list *kwl)
8719{
8720 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8721}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008722
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008723/*
8724 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8725 */
8726void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8727{
8728 LIST_DEL(&kwl->list);
8729 LIST_INIT(&kwl->list);
8730}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008731
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008732/* this function register new section in the haproxy configuration file.
8733 * <section_name> is the name of this new section and <section_parser>
8734 * is the called parser. If two section declaration have the same name,
8735 * only the first declared is used.
8736 */
8737int cfg_register_section(char *section_name,
8738 int (*section_parser)(const char *, int, char **, int))
8739{
8740 struct cfg_section *cs;
8741
8742 cs = calloc(1, sizeof(*cs));
8743 if (!cs) {
8744 Alert("register section '%s': out of memory.\n", section_name);
8745 return 0;
8746 }
8747
8748 cs->section_name = section_name;
8749 cs->section_parser = section_parser;
8750
8751 LIST_ADDQ(&sections, &cs->list);
8752
8753 return 1;
8754}
8755
Willy Tarreaubaaee002006-06-26 02:48:02 +02008756/*
8757 * Local variables:
8758 * c-indent-level: 8
8759 * c-basic-offset: 8
8760 * End:
8761 */