blob: 129cf17dc990952cc29656289b78779549b6017c [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 }
Thomas Holmes0809f262015-05-12 15:50:47 +01001769#ifdef USE_51DEGREES
1770 else if (strcmp(args[0], "51degrees-data-file") == 0) {
1771 if(!*(args[1])) {
Thomas Holmes4d441a72015-05-29 12:54:25 +01001772 Alert("parsing [%s:%d]: '%s' expects a filepath to a 51Degrees trie or pattern data file.\n", file, linenum, args[0]);
Thomas Holmes0809f262015-05-12 15:50:47 +01001773 err_code |= ERR_ALERT | ERR_FATAL;
1774 goto out;
1775 }
1776 global._51d_data_file_path = strdup(args[1]);
1777 }
1778 else if (strcmp(args[0], "51degrees-property-seperator") == 0) {
1779 if(!*(args[1])) {
Thomas Holmes4d441a72015-05-29 12:54:25 +01001780 Alert("parsing [%s:%d]: '%s' expects a single character.\n", file, linenum, args[0]);
Thomas Holmes0809f262015-05-12 15:50:47 +01001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784 if (strlen(args[1]) > 1) {
Thomas Holmes4d441a72015-05-29 12:54:25 +01001785 Alert("parsing [%s:%d]: '%s' expects a single character, got '%s'.\n", file, linenum, args[0], args[1]);
Thomas Holmes0809f262015-05-12 15:50:47 +01001786 err_code |= ERR_ALERT | ERR_FATAL;
1787 goto out;
1788 }
1789 global._51d_property_seperator = *args[1];
1790 }
1791 else if (strcmp(args[0], "51degrees-property-name-list") == 0) {
1792 int arg;
1793 struct _51d_property_names *name;
1794
1795 arg = 1;
1796 if (!*args[arg]) {
1797 Alert("parsing [%s:%d]: '%s' expects at least one 51Degrees property name.\n", file, linenum, args[0]);
1798 err_code |= ERR_ALERT | ERR_FATAL;
1799 goto out;
1800 }
1801
1802 LIST_INIT(&global._51d_property_names);
1803 while (*args[arg]) {
1804 name = calloc(1, sizeof(struct _51d_property_names));
1805 name->name = strdup(args[arg]);
1806 LIST_ADDQ(&global._51d_property_names, &name->list);
1807 ++arg;
1808 }
1809 }
1810#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001811 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001812 struct cfg_kw_list *kwl;
1813 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001814 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001815
1816 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1817 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1818 if (kwl->kw[index].section != CFG_GLOBAL)
1819 continue;
1820 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001821 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001822 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001823 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001824 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001825 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001826 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001827 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001828 err_code |= ERR_WARN;
1829 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001830 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001831 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001832 }
1833 }
1834 }
1835
Willy Tarreaubaaee002006-06-26 02:48:02 +02001836 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001837 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001838 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001839
Willy Tarreau058e9072009-07-20 09:30:05 +02001840 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001841 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001842 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001843}
1844
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001845void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001846{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001847 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001848 defproxy.mode = PR_MODE_TCP;
1849 defproxy.state = PR_STNEW;
1850 defproxy.maxconn = cfg_maxpconn;
1851 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001852 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001853
Simon Horman66183002013-02-23 10:16:43 +09001854 defproxy.defsrv.check.inter = DEF_CHKINTR;
1855 defproxy.defsrv.check.fastinter = 0;
1856 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001857 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1858 defproxy.defsrv.agent.fastinter = 0;
1859 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001860 defproxy.defsrv.check.rise = DEF_RISETIME;
1861 defproxy.defsrv.check.fall = DEF_FALLTIME;
1862 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1863 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001864 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001865 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001866 defproxy.defsrv.maxqueue = 0;
1867 defproxy.defsrv.minconn = 0;
1868 defproxy.defsrv.maxconn = 0;
1869 defproxy.defsrv.slowstart = 0;
1870 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1871 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1872 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001873
1874 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001875}
1876
Willy Tarreauade5ec42010-01-28 19:33:49 +01001877
Willy Tarreau63af98d2014-05-18 08:11:41 +02001878/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1879 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1880 * ERR_FATAL in case of error.
1881 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001882static int create_cond_regex_rule(const char *file, int line,
1883 struct proxy *px, int dir, int action, int flags,
1884 const char *cmd, const char *reg, const char *repl,
1885 const char **cond_start)
1886{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001887 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001888 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001889 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001890 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001891 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001892 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001893 int cs;
1894 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001895
1896 if (px == &defproxy) {
1897 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001898 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001899 goto err;
1900 }
1901
1902 if (*reg == 0) {
1903 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
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
1908 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001909 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001910
Willy Tarreau5321c422010-01-28 20:35:13 +01001911 if (cond_start &&
1912 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001913 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1914 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1915 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001916 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001917 goto err;
1918 }
1919 }
1920 else if (cond_start && **cond_start) {
1921 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1922 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001923 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001924 goto err;
1925 }
1926
Willy Tarreau63af98d2014-05-18 08:11:41 +02001927 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001928 (dir == SMP_OPT_DIR_REQ) ?
1929 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1930 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1931 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001932
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001933 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001934 if (!preg) {
1935 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001936 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001937 goto err;
1938 }
1939
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001940 cs = !(flags & REG_ICASE);
1941 cap = !(flags & REG_NOSUB);
1942 error = NULL;
1943 if (!regex_comp(reg, preg, cs, cap, &error)) {
1944 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1945 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001946 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001947 goto err;
1948 }
1949
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001950 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001951 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001952 if (repl && err) {
1953 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1954 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001955 ret_code |= ERR_ALERT | ERR_FATAL;
1956 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001957 }
1958
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001959 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001960 ret_code |= ERR_WARN;
1961
1962 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001963
Willy Tarreau63af98d2014-05-18 08:11:41 +02001964 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001965 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001966 err:
1967 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001968 free(errmsg);
1969 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001970}
1971
Willy Tarreaubaaee002006-06-26 02:48:02 +02001972/*
William Lallemand51097192015-04-14 16:35:22 +02001973 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001974 * Returns the error code, 0 if OK, or any combination of :
1975 * - ERR_ABORT: must abort ASAP
1976 * - ERR_FATAL: we can continue parsing but not start the service
1977 * - ERR_WARN: a warning has been emitted
1978 * - ERR_ALERT: an alert has been emitted
1979 * Only the two first ones can stop processing, the two others are just
1980 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001982int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1983{
1984 static struct peers *curpeers = NULL;
1985 struct peer *newpeer = NULL;
1986 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001987 struct bind_conf *bind_conf;
1988 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001989 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001990 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001991
1992 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001993 if (!*args[1]) {
1994 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001995 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001996 goto out;
1997 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001998
William Lallemand6e62fb62015-04-28 16:55:23 +02001999 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2000 goto out;
2001
Emeric Brun32da3c42010-09-23 18:39:19 +02002002 err = invalid_char(args[1]);
2003 if (err) {
2004 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2005 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002006 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002007 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002008 }
2009
2010 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2011 /*
2012 * If there are two proxies with the same name only following
2013 * combinations are allowed:
2014 */
2015 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002016 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 +02002017 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002018 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002019 }
2020 }
2021
2022 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2023 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2024 err_code |= ERR_ALERT | ERR_ABORT;
2025 goto out;
2026 }
2027
2028 curpeers->next = peers;
2029 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002030 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002031 curpeers->conf.line = linenum;
2032 curpeers->last_change = now.tv_sec;
2033 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002034 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 }
2036 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002037 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002038 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002039 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002040
2041 if (!*args[2]) {
2042 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2043 file, linenum, args[0]);
2044 err_code |= ERR_ALERT | ERR_FATAL;
2045 goto out;
2046 }
2047
2048 err = invalid_char(args[1]);
2049 if (err) {
2050 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2051 file, linenum, *err, args[1]);
2052 err_code |= ERR_ALERT | ERR_FATAL;
2053 goto out;
2054 }
2055
2056 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2057 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2058 err_code |= ERR_ALERT | ERR_ABORT;
2059 goto out;
2060 }
2061
2062 /* the peers are linked backwards first */
2063 curpeers->count++;
2064 newpeer->next = curpeers->remote;
2065 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002066 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002067 newpeer->conf.line = linenum;
2068
2069 newpeer->last_change = now.tv_sec;
2070 newpeer->id = strdup(args[1]);
2071
Willy Tarreau902636f2013-03-10 19:44:48 +01002072 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002073 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002074 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002075 err_code |= ERR_ALERT | ERR_FATAL;
2076 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002077 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002078
2079 proto = protocol_by_family(sk->ss_family);
2080 if (!proto || !proto->connect) {
2081 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2082 file, linenum, args[0], args[1]);
2083 err_code |= ERR_ALERT | ERR_FATAL;
2084 goto out;
2085 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002086
2087 if (port1 != port2) {
2088 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2089 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002090 err_code |= ERR_ALERT | ERR_FATAL;
2091 goto out;
2092 }
2093
Willy Tarreau2aa38802013-02-20 19:20:59 +01002094 if (!port1) {
2095 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2096 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002097 err_code |= ERR_ALERT | ERR_FATAL;
2098 goto out;
2099 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002100
Emeric Brun32da3c42010-09-23 18:39:19 +02002101 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002102 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002103 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002104 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002105
Emeric Brun32da3c42010-09-23 18:39:19 +02002106 if (strcmp(newpeer->id, localpeer) == 0) {
2107 /* Current is local peer, it define a frontend */
2108 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002109 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002110
2111 if (!curpeers->peers_fe) {
2112 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2113 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2114 err_code |= ERR_ALERT | ERR_ABORT;
2115 goto out;
2116 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002117
Willy Tarreau237250c2011-07-29 01:49:03 +02002118 init_new_proxy(curpeers->peers_fe);
2119 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002120 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002121 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2122 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002123 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002124
2125 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2126
Willy Tarreau902636f2013-03-10 19:44:48 +01002127 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2128 if (errmsg && *errmsg) {
2129 indent_msg(&errmsg, 2);
2130 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002131 }
2132 else
2133 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2134 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002135 err_code |= ERR_FATAL;
2136 goto out;
2137 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002138
2139 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002140 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002141 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2142 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002143 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002144 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002145 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002146 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002147 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2148 global.maxsock += l->maxconn;
2149 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002150 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002151 else {
2152 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2153 file, linenum, args[0], args[1],
2154 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2155 err_code |= ERR_FATAL;
2156 goto out;
2157 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 }
2159 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002160 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2161 curpeers->state = PR_STSTOPPED;
2162 }
2163 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2164 curpeers->state = PR_STNEW;
2165 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002166 else if (*args[0] != 0) {
2167 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2168 err_code |= ERR_ALERT | ERR_FATAL;
2169 goto out;
2170 }
2171
2172out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002173 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002174 return err_code;
2175}
2176
Baptiste Assmann325137d2015-04-13 23:40:55 +02002177/*
2178 * Parse a <resolvers> section.
2179 * Returns the error code, 0 if OK, or any combination of :
2180 * - ERR_ABORT: must abort ASAP
2181 * - ERR_FATAL: we can continue parsing but not start the service
2182 * - ERR_WARN: a warning has been emitted
2183 * - ERR_ALERT: an alert has been emitted
2184 * Only the two first ones can stop processing, the two others are just
2185 * indicators.
2186 */
2187int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2188{
2189 static struct dns_resolvers *curr_resolvers = NULL;
2190 struct dns_nameserver *newnameserver = NULL;
2191 const char *err;
2192 int err_code = 0;
2193 char *errmsg = NULL;
2194
2195 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2196 if (!*args[1]) {
2197 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2198 err_code |= ERR_ALERT | ERR_ABORT;
2199 goto out;
2200 }
2201
2202 err = invalid_char(args[1]);
2203 if (err) {
2204 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2205 file, linenum, *err, args[0], args[1]);
2206 err_code |= ERR_ALERT | ERR_ABORT;
2207 goto out;
2208 }
2209
2210 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2211 /* Error if two resolvers owns the same name */
2212 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2213 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2214 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2215 err_code |= ERR_ALERT | ERR_ABORT;
2216 }
2217 }
2218
2219 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2220 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2221 err_code |= ERR_ALERT | ERR_ABORT;
2222 goto out;
2223 }
2224
2225 /* default values */
2226 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2227 curr_resolvers->conf.file = strdup(file);
2228 curr_resolvers->conf.line = linenum;
2229 curr_resolvers->id = strdup(args[1]);
2230 curr_resolvers->query_ids = EB_ROOT;
2231 /* default hold period for valid is 10s */
2232 curr_resolvers->hold.valid = 10;
2233 curr_resolvers->timeout.retry = 1;
2234 curr_resolvers->resolve_retries = 3;
2235 LIST_INIT(&curr_resolvers->nameserver_list);
2236 LIST_INIT(&curr_resolvers->curr_resolution);
2237 }
2238 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2239 struct sockaddr_storage *sk;
2240 int port1, port2;
2241 struct protocol *proto;
2242
2243 if (!*args[2]) {
2244 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2245 file, linenum, args[0]);
2246 err_code |= ERR_ALERT | ERR_FATAL;
2247 goto out;
2248 }
2249
2250 err = invalid_char(args[1]);
2251 if (err) {
2252 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2253 file, linenum, *err, args[1]);
2254 err_code |= ERR_ALERT | ERR_FATAL;
2255 goto out;
2256 }
2257
2258 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2259 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2260 err_code |= ERR_ALERT | ERR_ABORT;
2261 goto out;
2262 }
2263
2264 /* the nameservers are linked backward first */
2265 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2266 curr_resolvers->count_nameservers++;
2267 newnameserver->resolvers = curr_resolvers;
2268 newnameserver->conf.file = strdup(file);
2269 newnameserver->conf.line = linenum;
2270 newnameserver->id = strdup(args[1]);
2271
2272 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2273 if (!sk) {
2274 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2275 err_code |= ERR_ALERT | ERR_FATAL;
2276 goto out;
2277 }
2278
2279 proto = protocol_by_family(sk->ss_family);
2280 if (!proto || !proto->connect) {
2281 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2282 file, linenum, args[0], args[1]);
2283 err_code |= ERR_ALERT | ERR_FATAL;
2284 goto out;
2285 }
2286
2287 if (port1 != port2) {
2288 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2289 file, linenum, args[0], args[1], args[2]);
2290 err_code |= ERR_ALERT | ERR_FATAL;
2291 goto out;
2292 }
2293
2294 newnameserver->addr = *sk;
2295 }
2296 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2297 const char *res;
2298 unsigned int time;
2299
2300 if (!*args[2]) {
2301 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2302 file, linenum, args[0]);
2303 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2304 err_code |= ERR_ALERT | ERR_FATAL;
2305 goto out;
2306 }
2307 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2308 if (res) {
2309 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2310 file, linenum, *res, args[0]);
2311 err_code |= ERR_ALERT | ERR_FATAL;
2312 goto out;
2313 }
2314 if (strcmp(args[1], "valid") == 0)
2315 curr_resolvers->hold.valid = time;
2316 else {
2317 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2318 file, linenum, args[0], args[1]);
2319 err_code |= ERR_ALERT | ERR_FATAL;
2320 goto out;
2321 }
2322
2323 }
2324 else if (strcmp(args[0], "resolve_retries") == 0) {
2325 if (!*args[1]) {
2326 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2327 file, linenum, args[0]);
2328 err_code |= ERR_ALERT | ERR_FATAL;
2329 goto out;
2330 }
2331 curr_resolvers->resolve_retries = atoi(args[1]);
2332 }
2333 else if (strcmp(args[0], "timeout") == 0) {
2334 const char *res;
2335 unsigned int timeout_retry;
2336
2337 if (!*args[2]) {
2338 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2339 file, linenum, args[0]);
2340 err_code |= ERR_ALERT | ERR_FATAL;
2341 goto out;
2342 }
2343 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2344 if (res) {
2345 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2346 file, linenum, *res, args[0]);
2347 err_code |= ERR_ALERT | ERR_FATAL;
2348 goto out;
2349 }
2350 curr_resolvers->timeout.retry = timeout_retry;
2351 } /* neither "nameserver" nor "resolvers" */
2352 else if (*args[0] != 0) {
2353 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 goto out;
2356 }
2357
2358 out:
2359 free(errmsg);
2360 return err_code;
2361}
Simon Horman0d16a402015-01-30 11:22:58 +09002362
2363/*
William Lallemand51097192015-04-14 16:35:22 +02002364 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002365 * Returns the error code, 0 if OK, or any combination of :
2366 * - ERR_ABORT: must abort ASAP
2367 * - ERR_FATAL: we can continue parsing but not start the service
2368 * - ERR_WARN: a warning has been emitted
2369 * - ERR_ALERT: an alert has been emitted
2370 * Only the two first ones can stop processing, the two others are just
2371 * indicators.
2372 */
2373int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2374{
2375 static struct mailers *curmailers = NULL;
2376 struct mailer *newmailer = NULL;
2377 const char *err;
2378 int err_code = 0;
2379 char *errmsg = NULL;
2380
2381 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2382 if (!*args[1]) {
2383 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2384 err_code |= ERR_ALERT | ERR_ABORT;
2385 goto out;
2386 }
2387
2388 err = invalid_char(args[1]);
2389 if (err) {
2390 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2391 file, linenum, *err, args[0], args[1]);
2392 err_code |= ERR_ALERT | ERR_ABORT;
2393 goto out;
2394 }
2395
2396 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2397 /*
2398 * If there are two proxies with the same name only following
2399 * combinations are allowed:
2400 */
2401 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002402 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 +09002403 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002404 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002405 }
2406 }
2407
2408 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2409 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2410 err_code |= ERR_ALERT | ERR_ABORT;
2411 goto out;
2412 }
2413
2414 curmailers->next = mailers;
2415 mailers = curmailers;
2416 curmailers->conf.file = strdup(file);
2417 curmailers->conf.line = linenum;
2418 curmailers->id = strdup(args[1]);
2419 }
2420 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2421 struct sockaddr_storage *sk;
2422 int port1, port2;
2423 struct protocol *proto;
2424
2425 if (!*args[2]) {
2426 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2427 file, linenum, args[0]);
2428 err_code |= ERR_ALERT | ERR_FATAL;
2429 goto out;
2430 }
2431
2432 err = invalid_char(args[1]);
2433 if (err) {
2434 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2435 file, linenum, *err, args[1]);
2436 err_code |= ERR_ALERT | ERR_FATAL;
2437 goto out;
2438 }
2439
2440 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2441 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2442 err_code |= ERR_ALERT | ERR_ABORT;
2443 goto out;
2444 }
2445
2446 /* the mailers are linked backwards first */
2447 curmailers->count++;
2448 newmailer->next = curmailers->mailer_list;
2449 curmailers->mailer_list = newmailer;
2450 newmailer->mailers = curmailers;
2451 newmailer->conf.file = strdup(file);
2452 newmailer->conf.line = linenum;
2453
2454 newmailer->id = strdup(args[1]);
2455
2456 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2457 if (!sk) {
2458 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2459 err_code |= ERR_ALERT | ERR_FATAL;
2460 goto out;
2461 }
2462
2463 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002464 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2465 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002466 file, linenum, args[0], args[1]);
2467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
2469 }
2470
2471 if (port1 != port2) {
2472 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2473 file, linenum, args[0], args[1], args[2]);
2474 err_code |= ERR_ALERT | ERR_FATAL;
2475 goto out;
2476 }
2477
2478 if (!port1) {
2479 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2480 file, linenum, args[0], args[1], args[2]);
2481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
2484
2485 newmailer->addr = *sk;
2486 newmailer->proto = proto;
2487 newmailer->xprt = &raw_sock;
2488 newmailer->sock_init_arg = NULL;
2489 } /* neither "mailer" nor "mailers" */
2490 else if (*args[0] != 0) {
2491 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495
2496out:
2497 free(errmsg);
2498 return err_code;
2499}
2500
Simon Horman9dc49962015-01-30 11:22:59 +09002501static void free_email_alert(struct proxy *p)
2502{
2503 free(p->email_alert.mailers.name);
2504 p->email_alert.mailers.name = NULL;
2505 free(p->email_alert.from);
2506 p->email_alert.from = NULL;
2507 free(p->email_alert.to);
2508 p->email_alert.to = NULL;
2509 free(p->email_alert.myhostname);
2510 p->email_alert.myhostname = NULL;
2511}
2512
Willy Tarreau3842f002009-06-14 11:39:52 +02002513int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002514{
2515 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002516 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002517 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002518 int rc;
2519 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002520 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002521 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002522 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002523 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002524 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002525
Willy Tarreau977b8e42006-12-29 14:19:17 +01002526 if (!strcmp(args[0], "listen"))
2527 rc = PR_CAP_LISTEN;
2528 else if (!strcmp(args[0], "frontend"))
2529 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002530 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002531 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002532 else
2533 rc = PR_CAP_NONE;
2534
2535 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002536 if (!*args[1]) {
2537 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2538 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2539 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002540 err_code |= ERR_ALERT | ERR_ABORT;
2541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002543
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002544 err = invalid_char(args[1]);
2545 if (err) {
2546 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2547 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002548 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002549 }
2550
Willy Tarreau8f50b682015-05-26 11:45:02 +02002551 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2552 if (curproxy) {
2553 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2554 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2555 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002556 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002557 }
2558
Willy Tarreaubaaee002006-06-26 02:48:02 +02002559 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2560 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002561 err_code |= ERR_ALERT | ERR_ABORT;
2562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002563 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002564
Willy Tarreau97cb7802010-01-03 20:23:58 +01002565 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002566 curproxy->next = proxy;
2567 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002568 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2569 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002570 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002571 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002572 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002573 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002574
William Lallemand6e62fb62015-04-28 16:55:23 +02002575 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2576 if (curproxy->cap & PR_CAP_FE)
2577 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002579 }
2580
2581 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002582 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002583 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002584
Willy Tarreaubaaee002006-06-26 02:48:02 +02002585 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002586 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002587 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002588 curproxy->no_options = defproxy.no_options;
2589 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002590 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002591 curproxy->except_net = defproxy.except_net;
2592 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002593 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002594 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002595
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002596 if (defproxy.fwdfor_hdr_len) {
2597 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2598 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2599 }
2600
Willy Tarreaub86db342009-11-30 11:50:16 +01002601 if (defproxy.orgto_hdr_len) {
2602 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2603 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2604 }
2605
Mark Lamourinec2247f02012-01-04 13:02:01 -05002606 if (defproxy.server_id_hdr_len) {
2607 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2608 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2609 }
2610
Willy Tarreau977b8e42006-12-29 14:19:17 +01002611 if (curproxy->cap & PR_CAP_FE) {
2612 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002613 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002614 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002615
2616 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002617 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2618 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002619
2620 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002622
Willy Tarreau977b8e42006-12-29 14:19:17 +01002623 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002624 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002625 curproxy->fullconn = defproxy.fullconn;
2626 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002627 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002628 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002629
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002630 if (defproxy.check_req) {
2631 curproxy->check_req = calloc(1, defproxy.check_len);
2632 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2633 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002634 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002635
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002636 if (defproxy.expect_str) {
2637 curproxy->expect_str = strdup(defproxy.expect_str);
2638 if (defproxy.expect_regex) {
2639 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002640 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2641 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002642 }
2643 }
2644
Willy Tarreau67402132012-05-31 20:40:20 +02002645 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002646 if (defproxy.cookie_name)
2647 curproxy->cookie_name = strdup(defproxy.cookie_name);
2648 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002649 if (defproxy.cookie_domain)
2650 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002651
Willy Tarreau31936852010-10-06 16:59:56 +02002652 if (defproxy.cookie_maxidle)
2653 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2654
2655 if (defproxy.cookie_maxlife)
2656 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2657
Emeric Brun647caf12009-06-30 17:57:00 +02002658 if (defproxy.rdp_cookie_name)
2659 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2660 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2661
Willy Tarreau01732802007-11-01 22:48:15 +01002662 if (defproxy.url_param_name)
2663 curproxy->url_param_name = strdup(defproxy.url_param_name);
2664 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002665
Benoitaffb4812009-03-25 13:02:10 +01002666 if (defproxy.hh_name)
2667 curproxy->hh_name = strdup(defproxy.hh_name);
2668 curproxy->hh_len = defproxy.hh_len;
2669 curproxy->hh_match_domain = defproxy.hh_match_domain;
2670
Willy Tarreauef9a3602012-12-08 22:29:20 +01002671 if (defproxy.conn_src.iface_name)
2672 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2673 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002674 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002675#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002676 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002677#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002678 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002679
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002680 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002681 if (defproxy.capture_name)
2682 curproxy->capture_name = strdup(defproxy.capture_name);
2683 curproxy->capture_namelen = defproxy.capture_namelen;
2684 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002685 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686
Willy Tarreau977b8e42006-12-29 14:19:17 +01002687 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002688 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002689 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002690 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002691 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002692 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002693 curproxy->mon_net = defproxy.mon_net;
2694 curproxy->mon_mask = defproxy.mon_mask;
2695 if (defproxy.monitor_uri)
2696 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2697 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002698 if (defproxy.defbe.name)
2699 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002700
2701 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002702 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2703 if (curproxy->conf.logformat_string &&
2704 curproxy->conf.logformat_string != default_http_log_format &&
2705 curproxy->conf.logformat_string != default_tcp_log_format &&
2706 curproxy->conf.logformat_string != clf_http_log_format)
2707 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2708
2709 if (defproxy.conf.lfs_file) {
2710 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2711 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2712 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002713 }
2714
2715 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002716 curproxy->timeout.connect = defproxy.timeout.connect;
2717 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002718 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002719 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002720 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002721 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002722 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002723 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002724 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002725 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002726 }
2727
Willy Tarreaubaaee002006-06-26 02:48:02 +02002728 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002729 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002730
2731 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002732 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002733 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002734 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002735 LIST_INIT(&node->list);
2736 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2737 }
2738
Willy Tarreau62a61232013-04-12 18:13:46 +02002739 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2740 if (curproxy->conf.uniqueid_format_string)
2741 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2742
Willy Tarreau094af4e2015-01-07 15:03:42 +01002743 if (defproxy.log_tag)
2744 curproxy->log_tag = strdup(defproxy.log_tag);
2745
Willy Tarreau62a61232013-04-12 18:13:46 +02002746 if (defproxy.conf.uif_file) {
2747 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2748 curproxy->conf.uif_line = defproxy.conf.uif_line;
2749 }
William Lallemanda73203e2012-03-12 12:48:57 +01002750
2751 /* copy default header unique id */
2752 if (defproxy.header_unique_id)
2753 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2754
William Lallemand82fe75c2012-10-23 10:25:10 +02002755 /* default compression options */
2756 if (defproxy.comp != NULL) {
2757 curproxy->comp = calloc(1, sizeof(struct comp));
2758 curproxy->comp->algos = defproxy.comp->algos;
2759 curproxy->comp->types = defproxy.comp->types;
2760 }
2761
Willy Tarreaubaaee002006-06-26 02:48:02 +02002762 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002763 curproxy->conf.used_listener_id = EB_ROOT;
2764 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002765
Simon Horman98637e52014-06-20 12:30:16 +09002766 if (defproxy.check_path)
2767 curproxy->check_path = strdup(defproxy.check_path);
2768 if (defproxy.check_command)
2769 curproxy->check_command = strdup(defproxy.check_command);
2770
Simon Horman9dc49962015-01-30 11:22:59 +09002771 if (defproxy.email_alert.mailers.name)
2772 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2773 if (defproxy.email_alert.from)
2774 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2775 if (defproxy.email_alert.to)
2776 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2777 if (defproxy.email_alert.myhostname)
2778 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002779 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002780
Willy Tarreau93893792009-07-23 13:19:11 +02002781 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002782 }
2783 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2784 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002785 /* FIXME-20070101: we should do this too at the end of the
2786 * config parsing to free all default values.
2787 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002788 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2789 err_code |= ERR_ABORT;
2790 goto out;
2791 }
2792
Willy Tarreaua534fea2008-08-03 12:19:50 +02002793 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002794 free(defproxy.check_command);
2795 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002796 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002797 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002798 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002799 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002800 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002801 free(defproxy.capture_name);
2802 free(defproxy.monitor_uri);
2803 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002804 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002805 free(defproxy.fwdfor_hdr_name);
2806 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002807 free(defproxy.orgto_hdr_name);
2808 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002809 free(defproxy.server_id_hdr_name);
2810 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002811 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002812 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002813 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002814 free(defproxy.expect_regex);
2815 defproxy.expect_regex = NULL;
2816 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002817
Willy Tarreau62a61232013-04-12 18:13:46 +02002818 if (defproxy.conf.logformat_string != default_http_log_format &&
2819 defproxy.conf.logformat_string != default_tcp_log_format &&
2820 defproxy.conf.logformat_string != clf_http_log_format)
2821 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002822
Willy Tarreau62a61232013-04-12 18:13:46 +02002823 free(defproxy.conf.uniqueid_format_string);
2824 free(defproxy.conf.lfs_file);
2825 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002826 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002827 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002828
Willy Tarreaua534fea2008-08-03 12:19:50 +02002829 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002830 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002831
Willy Tarreaubaaee002006-06-26 02:48:02 +02002832 /* we cannot free uri_auth because it might already be used */
2833 init_default_instance();
2834 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002835 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2836 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002837 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002838 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839 }
2840 else if (curproxy == NULL) {
2841 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002842 err_code |= ERR_ALERT | ERR_FATAL;
2843 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002844 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002845
2846 /* update the current file and line being parsed */
2847 curproxy->conf.args.file = curproxy->conf.file;
2848 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002849
2850 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002851 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2852 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2853 if (err_code & ERR_FATAL)
2854 goto out;
2855 }
2856 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002857 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002858 int cur_arg;
2859
Willy Tarreaubaaee002006-06-26 02:48:02 +02002860 if (curproxy == &defproxy) {
2861 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002862 err_code |= ERR_ALERT | ERR_FATAL;
2863 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002864 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002865 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002866 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002867
Willy Tarreau24709282013-03-10 21:32:12 +01002868 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002869 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002870 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002871 err_code |= ERR_ALERT | ERR_FATAL;
2872 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002873 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002874
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002875 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002876
2877 /* use default settings for unix sockets */
2878 bind_conf->ux.uid = global.unix_bind.ux.uid;
2879 bind_conf->ux.gid = global.unix_bind.ux.gid;
2880 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002881
2882 /* NOTE: the following line might create several listeners if there
2883 * are comma-separated IPs or port ranges. So all further processing
2884 * will have to be applied to all listeners created after last_listen.
2885 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002886 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2887 if (errmsg && *errmsg) {
2888 indent_msg(&errmsg, 2);
2889 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002890 }
2891 else
2892 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2893 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002894 err_code |= ERR_ALERT | ERR_FATAL;
2895 goto out;
2896 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002897
Willy Tarreau4348fad2012-09-20 16:48:07 +02002898 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2899 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002900 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002901 }
2902
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002903 cur_arg = 2;
2904 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002905 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002906 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002907 char *err;
2908
Willy Tarreau26982662012-09-12 23:17:10 +02002909 kw = bind_find_kw(args[cur_arg]);
2910 if (kw) {
2911 char *err = NULL;
2912 int code;
2913
2914 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002915 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2916 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002917 cur_arg += 1 + kw->skip ;
2918 err_code |= ERR_ALERT | ERR_FATAL;
2919 goto out;
2920 }
2921
Willy Tarreau4348fad2012-09-20 16:48:07 +02002922 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002923 err_code |= code;
2924
2925 if (code) {
2926 if (err && *err) {
2927 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002928 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002929 }
2930 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002931 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2932 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002933 if (code & ERR_FATAL) {
2934 free(err);
2935 cur_arg += 1 + kw->skip;
2936 goto out;
2937 }
2938 }
2939 free(err);
2940 cur_arg += 1 + kw->skip;
2941 continue;
2942 }
2943
Willy Tarreau8638f482012-09-18 18:01:17 +02002944 err = NULL;
2945 if (!bind_dumped) {
2946 bind_dump_kws(&err);
2947 indent_msg(&err, 4);
2948 bind_dumped = 1;
2949 }
2950
2951 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2952 file, linenum, args[0], args[1], args[cur_arg],
2953 err ? " Registered keywords :" : "", err ? err : "");
2954 free(err);
2955
Willy Tarreau93893792009-07-23 13:19:11 +02002956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002958 }
Willy Tarreau93893792009-07-23 13:19:11 +02002959 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002960 }
2961 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002962 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002963 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2964 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002968 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002969 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002970
Willy Tarreaubaaee002006-06-26 02:48:02 +02002971 /* flush useless bits */
2972 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002973 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002975 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002976 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002977 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002978
William Lallemanddf1425a2015-04-28 20:17:49 +02002979 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2980 goto out;
2981
Willy Tarreau1c47f852006-07-09 08:22:27 +02002982 if (!*args[1]) {
2983 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2984 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002987 }
2988
Willy Tarreaua534fea2008-08-03 12:19:50 +02002989 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002990 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002991 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002992 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002993 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2994
Willy Tarreau93893792009-07-23 13:19:11 +02002995 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002996 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002997 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002998 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2999 goto out;
3000
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3002 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3003 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3004 else {
3005 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003006 err_code |= ERR_ALERT | ERR_FATAL;
3007 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003008 }
3009 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003010 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003011 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003012
3013 if (curproxy == &defproxy) {
3014 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3015 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003016 err_code |= ERR_ALERT | ERR_FATAL;
3017 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003018 }
3019
William Lallemanddf1425a2015-04-28 20:17:49 +02003020 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3021 goto out;
3022
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003023 if (!*args[1]) {
3024 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3025 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003026 err_code |= ERR_ALERT | ERR_FATAL;
3027 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003028 }
3029
3030 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003031 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003032 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003033
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003034 if (curproxy->uuid <= 0) {
3035 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003036 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003037 err_code |= ERR_ALERT | ERR_FATAL;
3038 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003039 }
3040
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003041 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3042 if (node) {
3043 struct proxy *target = container_of(node, struct proxy, conf.id);
3044 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3045 file, linenum, proxy_type_str(curproxy), curproxy->id,
3046 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3047 err_code |= ERR_ALERT | ERR_FATAL;
3048 goto out;
3049 }
3050 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003051 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003052 else if (!strcmp(args[0], "description")) {
3053 int i, len=0;
3054 char *d;
3055
Cyril Bonté99ed3272010-01-24 23:29:44 +01003056 if (curproxy == &defproxy) {
3057 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3058 file, linenum, args[0]);
3059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
3061 }
3062
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003063 if (!*args[1]) {
3064 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3065 file, linenum, args[0]);
3066 return -1;
3067 }
3068
Willy Tarreau348acfe2014-04-14 15:00:39 +02003069 for (i = 1; *args[i]; i++)
3070 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003071
3072 d = (char *)calloc(1, len);
3073 curproxy->desc = d;
3074
Willy Tarreau348acfe2014-04-14 15:00:39 +02003075 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3076 for (i = 2; *args[i]; i++)
3077 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003078
3079 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003080 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003081 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 curproxy->state = PR_STSTOPPED;
3084 }
3085 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003086 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003088 curproxy->state = PR_STNEW;
3089 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003090 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3091 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003092 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003093
3094 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003095 unsigned int low, high;
3096
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003097 if (strcmp(args[cur_arg], "all") == 0) {
3098 set = 0;
3099 break;
3100 }
3101 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003102 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003103 }
3104 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003105 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003106 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003107 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003108 char *dash = strchr(args[cur_arg], '-');
3109
3110 low = high = str2uic(args[cur_arg]);
3111 if (dash)
3112 high = str2uic(dash + 1);
3113
3114 if (high < low) {
3115 unsigned int swap = low;
3116 low = high;
3117 high = swap;
3118 }
3119
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003120 if (low < 1 || high > LONGBITS) {
3121 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3122 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003123 err_code |= ERR_ALERT | ERR_FATAL;
3124 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003125 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003126 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003127 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003128 }
3129 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003130 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3131 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003132 err_code |= ERR_ALERT | ERR_FATAL;
3133 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003134 }
3135 cur_arg++;
3136 }
3137 curproxy->bind_proc = set;
3138 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003139 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003140 if (curproxy == &defproxy) {
3141 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003142 err_code |= ERR_ALERT | ERR_FATAL;
3143 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003144 }
3145
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003146 err = invalid_char(args[1]);
3147 if (err) {
3148 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3149 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003150 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003151 }
3152
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003153 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003154 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3155 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003156 err_code |= ERR_ALERT | ERR_FATAL;
3157 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003158 }
3159 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3161 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162
Willy Tarreau977b8e42006-12-29 14:19:17 +01003163 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003164 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003165
Willy Tarreaubaaee002006-06-26 02:48:02 +02003166 if (*(args[1]) == 0) {
3167 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3168 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003169 err_code |= ERR_ALERT | ERR_FATAL;
3170 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003171 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003172
Willy Tarreau67402132012-05-31 20:40:20 +02003173 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003174 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003175 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003176 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003177 curproxy->cookie_name = strdup(args[1]);
3178 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003179
Willy Tarreaubaaee002006-06-26 02:48:02 +02003180 cur_arg = 2;
3181 while (*(args[cur_arg])) {
3182 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003183 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003184 }
3185 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003186 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003187 }
3188 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003189 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003190 }
3191 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003192 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003193 }
3194 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003195 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003197 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003198 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003199 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003200 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003201 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003202 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003203 else if (!strcmp(args[cur_arg], "httponly")) {
3204 curproxy->ck_opts |= PR_CK_HTTPONLY;
3205 }
3206 else if (!strcmp(args[cur_arg], "secure")) {
3207 curproxy->ck_opts |= PR_CK_SECURE;
3208 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003209 else if (!strcmp(args[cur_arg], "domain")) {
3210 if (!*args[cur_arg + 1]) {
3211 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3212 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003215 }
3216
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003217 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003218 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003219 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3220 " dots nor does not start with a dot."
3221 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003222 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003223 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003224 }
3225
3226 err = invalid_domainchar(args[cur_arg + 1]);
3227 if (err) {
3228 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3229 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003230 err_code |= ERR_ALERT | ERR_FATAL;
3231 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003232 }
3233
Willy Tarreau68a897b2009-12-03 23:28:34 +01003234 if (!curproxy->cookie_domain) {
3235 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3236 } else {
3237 /* one domain was already specified, add another one by
3238 * building the string which will be returned along with
3239 * the cookie.
3240 */
3241 char *new_ptr;
3242 int new_len = strlen(curproxy->cookie_domain) +
3243 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3244 new_ptr = malloc(new_len);
3245 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3246 free(curproxy->cookie_domain);
3247 curproxy->cookie_domain = new_ptr;
3248 }
Willy Tarreau31936852010-10-06 16:59:56 +02003249 cur_arg++;
3250 }
3251 else if (!strcmp(args[cur_arg], "maxidle")) {
3252 unsigned int maxidle;
3253 const char *res;
3254
3255 if (!*args[cur_arg + 1]) {
3256 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3257 file, linenum, args[cur_arg]);
3258 err_code |= ERR_ALERT | ERR_FATAL;
3259 goto out;
3260 }
3261
3262 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3263 if (res) {
3264 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3265 file, linenum, *res, args[cur_arg]);
3266 err_code |= ERR_ALERT | ERR_FATAL;
3267 goto out;
3268 }
3269 curproxy->cookie_maxidle = maxidle;
3270 cur_arg++;
3271 }
3272 else if (!strcmp(args[cur_arg], "maxlife")) {
3273 unsigned int maxlife;
3274 const char *res;
3275
3276 if (!*args[cur_arg + 1]) {
3277 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3278 file, linenum, args[cur_arg]);
3279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
3281 }
3282
3283 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3284 if (res) {
3285 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3286 file, linenum, *res, args[cur_arg]);
3287 err_code |= ERR_ALERT | ERR_FATAL;
3288 goto out;
3289 }
3290 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003291 cur_arg++;
3292 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003293 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003294 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 +02003295 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003296 err_code |= ERR_ALERT | ERR_FATAL;
3297 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003298 }
3299 cur_arg++;
3300 }
Willy Tarreau67402132012-05-31 20:40:20 +02003301 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3303 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003304 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
3306
Willy Tarreau67402132012-05-31 20:40:20 +02003307 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3309 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003310 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003311 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003312
Willy Tarreau67402132012-05-31 20:40:20 +02003313 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003314 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3315 file, linenum);
3316 err_code |= ERR_ALERT | ERR_FATAL;
3317 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003318 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003319 else if (!strcmp(args[0], "email-alert")) {
3320 if (*(args[1]) == 0) {
3321 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3322 file, linenum, args[0]);
3323 err_code |= ERR_ALERT | ERR_FATAL;
3324 goto out;
3325 }
3326
3327 if (!strcmp(args[1], "from")) {
3328 if (*(args[1]) == 0) {
3329 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3330 file, linenum, args[1]);
3331 err_code |= ERR_ALERT | ERR_FATAL;
3332 goto out;
3333 }
3334 free(curproxy->email_alert.from);
3335 curproxy->email_alert.from = strdup(args[2]);
3336 }
3337 else if (!strcmp(args[1], "mailers")) {
3338 if (*(args[1]) == 0) {
3339 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3340 file, linenum, args[1]);
3341 err_code |= ERR_ALERT | ERR_FATAL;
3342 goto out;
3343 }
3344 free(curproxy->email_alert.mailers.name);
3345 curproxy->email_alert.mailers.name = strdup(args[2]);
3346 }
3347 else if (!strcmp(args[1], "myhostname")) {
3348 if (*(args[1]) == 0) {
3349 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3350 file, linenum, args[1]);
3351 err_code |= ERR_ALERT | ERR_FATAL;
3352 goto out;
3353 }
3354 free(curproxy->email_alert.myhostname);
3355 curproxy->email_alert.myhostname = strdup(args[2]);
3356 }
Simon Horman64e34162015-02-06 11:11:57 +09003357 else if (!strcmp(args[1], "level")) {
3358 curproxy->email_alert.level = get_log_level(args[2]);
3359 if (curproxy->email_alert.level < 0) {
3360 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3361 file, linenum, args[1], args[2]);
3362 err_code |= ERR_ALERT | ERR_FATAL;
3363 goto out;
3364 }
3365 }
Simon Horman9dc49962015-01-30 11:22:59 +09003366 else if (!strcmp(args[1], "to")) {
3367 if (*(args[1]) == 0) {
3368 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3369 file, linenum, args[1]);
3370 err_code |= ERR_ALERT | ERR_FATAL;
3371 goto out;
3372 }
3373 free(curproxy->email_alert.to);
3374 curproxy->email_alert.to = strdup(args[2]);
3375 }
3376 else {
3377 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3378 file, linenum, args[1]);
3379 err_code |= ERR_ALERT | ERR_FATAL;
3380 goto out;
3381 }
Simon Horman64e34162015-02-06 11:11:57 +09003382 /* Indicate that the email_alert is at least partially configured */
3383 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003384 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003385 else if (!strcmp(args[0], "external-check")) {
3386 if (*(args[1]) == 0) {
3387 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3388 file, linenum, args[0]);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
3392
3393 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003394 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3395 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003396 if (*(args[1]) == 0) {
3397 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3398 file, linenum, args[1]);
3399 err_code |= ERR_ALERT | ERR_FATAL;
3400 goto out;
3401 }
3402 free(curproxy->check_command);
3403 curproxy->check_command = strdup(args[2]);
3404 }
3405 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003406 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3407 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003408 if (*(args[1]) == 0) {
3409 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3410 file, linenum, args[1]);
3411 err_code |= ERR_ALERT | ERR_FATAL;
3412 goto out;
3413 }
3414 free(curproxy->check_path);
3415 curproxy->check_path = strdup(args[2]);
3416 }
3417 else {
3418 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3419 file, linenum, args[1]);
3420 err_code |= ERR_ALERT | ERR_FATAL;
3421 goto out;
3422 }
3423 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003424 else if (!strcmp(args[0], "persist")) { /* persist */
3425 if (*(args[1]) == 0) {
3426 Alert("parsing [%s:%d] : missing 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
3432 if (!strncmp(args[1], "rdp-cookie", 10)) {
3433 curproxy->options2 |= PR_O2_RDPC_PRST;
3434
Emeric Brunb982a3d2010-01-04 15:45:53 +01003435 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003436 const char *beg, *end;
3437
3438 beg = args[1] + 11;
3439 end = strchr(beg, ')');
3440
William Lallemanddf1425a2015-04-28 20:17:49 +02003441 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3442 goto out;
3443
Emeric Brun647caf12009-06-30 17:57:00 +02003444 if (!end || end == beg) {
3445 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3446 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003449 }
3450
3451 free(curproxy->rdp_cookie_name);
3452 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3453 curproxy->rdp_cookie_len = end-beg;
3454 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003455 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003456 free(curproxy->rdp_cookie_name);
3457 curproxy->rdp_cookie_name = strdup("msts");
3458 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3459 }
3460 else { /* syntax */
3461 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3462 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003463 err_code |= ERR_ALERT | ERR_FATAL;
3464 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003465 }
3466 }
3467 else {
3468 Alert("parsing [%s:%d] : unknown persist method.\n",
3469 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003470 err_code |= ERR_ALERT | ERR_FATAL;
3471 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003472 }
3473 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003474 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003475 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003476
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003477 if (curproxy == &defproxy) {
3478 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3479 err_code |= ERR_ALERT | ERR_FATAL;
3480 goto out;
3481 }
3482
Willy Tarreau977b8e42006-12-29 14:19:17 +01003483 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003485
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003487 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003488 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003489 err_code |= ERR_ALERT | ERR_FATAL;
3490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003491 }
3492 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003493 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003494 curproxy->appsession_name = strdup(args[1]);
3495 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3496 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003497 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3498 if (err) {
3499 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3500 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003501 err_code |= ERR_ALERT | ERR_FATAL;
3502 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003503 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003504 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003505
Willy Tarreau51041c72007-09-09 21:56:53 +02003506 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3507 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003508 err_code |= ERR_ALERT | ERR_ABORT;
3509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003510 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003511
3512 cur_arg = 6;
3513 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003514 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3515 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003516 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003517 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003518 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003519 } else if (!strcmp(args[cur_arg], "prefix")) {
3520 curproxy->options2 |= PR_O2_AS_PFX;
3521 } else if (!strcmp(args[cur_arg], "mode")) {
3522 if (!*args[cur_arg + 1]) {
3523 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3524 file, linenum, args[0], args[cur_arg]);
3525 err_code |= ERR_ALERT | ERR_FATAL;
3526 goto out;
3527 }
3528
3529 cur_arg++;
3530 if (!strcmp(args[cur_arg], "query-string")) {
3531 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3532 curproxy->options2 |= PR_O2_AS_M_QS;
3533 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3534 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3535 curproxy->options2 |= PR_O2_AS_M_PP;
3536 } else {
3537 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3538 err_code |= ERR_ALERT | ERR_FATAL;
3539 goto out;
3540 }
3541 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003542 cur_arg++;
3543 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003544 } /* Url App Session */
3545 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003546 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003547 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003548
Willy Tarreaubaaee002006-06-26 02:48:02 +02003549 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003550 if (curproxy == &defproxy) {
3551 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3552 err_code |= ERR_ALERT | ERR_FATAL;
3553 goto out;
3554 }
3555
William Lallemand1a748ae2015-05-19 16:37:23 +02003556 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3557 goto out;
3558
Willy Tarreaubaaee002006-06-26 02:48:02 +02003559 if (*(args[4]) == 0) {
3560 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3561 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003562 err_code |= ERR_ALERT | ERR_FATAL;
3563 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003564 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003565 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003566 curproxy->capture_name = strdup(args[2]);
3567 curproxy->capture_namelen = strlen(curproxy->capture_name);
3568 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003569 curproxy->to_log |= LW_COOKIE;
3570 }
3571 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3572 struct cap_hdr *hdr;
3573
3574 if (curproxy == &defproxy) {
3575 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 +02003576 err_code |= ERR_ALERT | ERR_FATAL;
3577 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003578 }
3579
William Lallemand1a748ae2015-05-19 16:37:23 +02003580 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3581 goto out;
3582
Willy Tarreaubaaee002006-06-26 02:48:02 +02003583 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3584 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3585 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003588 }
3589
3590 hdr = calloc(sizeof(struct cap_hdr), 1);
3591 hdr->next = curproxy->req_cap;
3592 hdr->name = strdup(args[3]);
3593 hdr->namelen = strlen(args[3]);
3594 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003595 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003596 hdr->index = curproxy->nb_req_cap++;
3597 curproxy->req_cap = hdr;
3598 curproxy->to_log |= LW_REQHDR;
3599 }
3600 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3601 struct cap_hdr *hdr;
3602
3603 if (curproxy == &defproxy) {
3604 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 +02003605 err_code |= ERR_ALERT | ERR_FATAL;
3606 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003607 }
3608
William Lallemand1a748ae2015-05-19 16:37:23 +02003609 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3610 goto out;
3611
Willy Tarreaubaaee002006-06-26 02:48:02 +02003612 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3613 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3614 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003615 err_code |= ERR_ALERT | ERR_FATAL;
3616 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003617 }
3618 hdr = calloc(sizeof(struct cap_hdr), 1);
3619 hdr->next = curproxy->rsp_cap;
3620 hdr->name = strdup(args[3]);
3621 hdr->namelen = strlen(args[3]);
3622 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003623 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003624 hdr->index = curproxy->nb_rsp_cap++;
3625 curproxy->rsp_cap = hdr;
3626 curproxy->to_log |= LW_RSPHDR;
3627 }
3628 else {
3629 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3630 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003631 err_code |= ERR_ALERT | ERR_FATAL;
3632 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003633 }
3634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003636 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003638
William Lallemanddf1425a2015-04-28 20:17:49 +02003639 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3640 goto out;
3641
Willy Tarreaubaaee002006-06-26 02:48:02 +02003642 if (*(args[1]) == 0) {
3643 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3644 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003647 }
3648 curproxy->conn_retries = atol(args[1]);
3649 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003650 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003651 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003652
3653 if (curproxy == &defproxy) {
3654 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3655 err_code |= ERR_ALERT | ERR_FATAL;
3656 goto out;
3657 }
3658
Willy Tarreau20b0de52012-12-24 15:45:22 +01003659 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3660 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3661 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3662 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003663 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003664 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3665 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 +01003666 file, linenum, args[0]);
3667 err_code |= ERR_WARN;
3668 }
3669
Willy Tarreauff011f22011-01-06 17:51:27 +01003670 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003671
Willy Tarreauff011f22011-01-06 17:51:27 +01003672 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003673 err_code |= ERR_ALERT | ERR_ABORT;
3674 goto out;
3675 }
3676
Willy Tarreau5002f572014-04-23 01:32:02 +02003677 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003678 err_code |= warnif_cond_conflicts(rule->cond,
3679 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3680 file, linenum);
3681
Willy Tarreauff011f22011-01-06 17:51:27 +01003682 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003683 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003684 else if (!strcmp(args[0], "http-response")) { /* response access control */
3685 struct http_res_rule *rule;
3686
3687 if (curproxy == &defproxy) {
3688 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3689 err_code |= ERR_ALERT | ERR_FATAL;
3690 goto out;
3691 }
3692
3693 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3694 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3695 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3696 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3697 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3698 file, linenum, args[0]);
3699 err_code |= ERR_WARN;
3700 }
3701
3702 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3703
3704 if (!rule) {
3705 err_code |= ERR_ALERT | ERR_ABORT;
3706 goto out;
3707 }
3708
3709 err_code |= warnif_cond_conflicts(rule->cond,
3710 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3711 file, linenum);
3712
3713 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3714 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003715 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3716 /* set the header name and length into the proxy structure */
3717 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3718 err_code |= ERR_WARN;
3719
3720 if (!*args[1]) {
3721 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3722 file, linenum, args[0]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726
3727 /* set the desired header name */
3728 free(curproxy->server_id_hdr_name);
3729 curproxy->server_id_hdr_name = strdup(args[1]);
3730 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3731 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003732 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003733 struct http_req_rule *rule;
3734
Willy Tarreaub099aca2008-10-12 17:26:37 +02003735 if (curproxy == &defproxy) {
3736 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003737 err_code |= ERR_ALERT | ERR_FATAL;
3738 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003739 }
3740
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003741 /* emulate "block" using "http-request block". Since these rules are supposed to
3742 * be processed before all http-request rules, we put them into their own list
3743 * and will insert them at the end.
3744 */
3745 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3746 if (!rule) {
3747 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003748 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003749 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003750 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3751 err_code |= warnif_cond_conflicts(rule->cond,
3752 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3753 file, linenum);
3754 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003755
3756 if (!already_warned(WARN_BLOCK_DEPRECATED))
3757 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]);
3758
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003759 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003760 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003761 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003762
Cyril Bonté99ed3272010-01-24 23:29:44 +01003763 if (curproxy == &defproxy) {
3764 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3765 err_code |= ERR_ALERT | ERR_FATAL;
3766 goto out;
3767 }
3768
Willy Tarreaube4653b2015-05-28 15:26:58 +02003769 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003770 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3771 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003772 err_code |= ERR_ALERT | ERR_FATAL;
3773 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003774 }
3775
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003776 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003777 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003778 err_code |= warnif_cond_conflicts(rule->cond,
3779 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3780 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003781 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003782 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003783 struct switching_rule *rule;
3784
Willy Tarreaub099aca2008-10-12 17:26:37 +02003785 if (curproxy == &defproxy) {
3786 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003789 }
3790
Willy Tarreau55ea7572007-06-17 19:56:27 +02003791 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003793
3794 if (*(args[1]) == 0) {
3795 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003798 }
3799
Willy Tarreauf51658d2014-04-23 01:21:56 +02003800 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3801 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3802 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3803 file, linenum, errmsg);
3804 err_code |= ERR_ALERT | ERR_FATAL;
3805 goto out;
3806 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003807
Willy Tarreauf51658d2014-04-23 01:21:56 +02003808 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003809 }
3810
3811 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3812 rule->cond = cond;
3813 rule->be.name = strdup(args[1]);
3814 LIST_INIT(&rule->list);
3815 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3816 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003817 else if (strcmp(args[0], "use-server") == 0) {
3818 struct server_rule *rule;
3819
3820 if (curproxy == &defproxy) {
3821 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
3825
3826 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3827 err_code |= ERR_WARN;
3828
3829 if (*(args[1]) == 0) {
3830 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3831 err_code |= ERR_ALERT | ERR_FATAL;
3832 goto out;
3833 }
3834
3835 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3836 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3837 file, linenum, args[0]);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840 }
3841
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003842 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3843 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3844 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003845 err_code |= ERR_ALERT | ERR_FATAL;
3846 goto out;
3847 }
3848
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003849 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003850
3851 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3852 rule->cond = cond;
3853 rule->srv.name = strdup(args[1]);
3854 LIST_INIT(&rule->list);
3855 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3856 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3857 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003858 else if ((!strcmp(args[0], "force-persist")) ||
3859 (!strcmp(args[0], "ignore-persist"))) {
3860 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003861
3862 if (curproxy == &defproxy) {
3863 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3864 err_code |= ERR_ALERT | ERR_FATAL;
3865 goto out;
3866 }
3867
3868 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3869 err_code |= ERR_WARN;
3870
Willy Tarreauef6494c2010-01-28 17:12:36 +01003871 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003872 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3873 file, linenum, args[0]);
3874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
3876 }
3877
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003878 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3879 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3880 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003881 err_code |= ERR_ALERT | ERR_FATAL;
3882 goto out;
3883 }
3884
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003885 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3886 * where force-persist is applied.
3887 */
3888 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003889
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003890 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003891 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003892 if (!strcmp(args[0], "force-persist")) {
3893 rule->type = PERSIST_TYPE_FORCE;
3894 } else {
3895 rule->type = PERSIST_TYPE_IGNORE;
3896 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003897 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003898 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003899 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003900 else if (!strcmp(args[0], "stick-table")) {
3901 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003902 struct proxy *other;
3903
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003904 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003905 if (other) {
3906 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3907 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3908 err_code |= ERR_ALERT | ERR_FATAL;
3909 goto out;
3910 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003911
Emeric Brun32da3c42010-09-23 18:39:19 +02003912 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003913 curproxy->table.type = (unsigned int)-1;
3914 while (*args[myidx]) {
3915 const char *err;
3916
3917 if (strcmp(args[myidx], "size") == 0) {
3918 myidx++;
3919 if (!*(args[myidx])) {
3920 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3921 file, linenum, args[myidx-1]);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
3924 }
3925 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3926 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3927 file, linenum, *err, args[myidx-1]);
3928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003931 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003932 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003933 else if (strcmp(args[myidx], "peers") == 0) {
3934 myidx++;
Godbach50523162013-12-11 19:48:57 +08003935 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003936 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3937 file, linenum, args[myidx-1]);
3938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Godbach50523162013-12-11 19:48:57 +08003940 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003941 curproxy->table.peers.name = strdup(args[myidx++]);
3942 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003943 else if (strcmp(args[myidx], "expire") == 0) {
3944 myidx++;
3945 if (!*(args[myidx])) {
3946 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3947 file, linenum, args[myidx-1]);
3948 err_code |= ERR_ALERT | ERR_FATAL;
3949 goto out;
3950 }
3951 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3952 if (err) {
3953 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3954 file, linenum, *err, args[myidx-1]);
3955 err_code |= ERR_ALERT | ERR_FATAL;
3956 goto out;
3957 }
3958 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003959 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003960 }
3961 else if (strcmp(args[myidx], "nopurge") == 0) {
3962 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003963 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003964 }
3965 else if (strcmp(args[myidx], "type") == 0) {
3966 myidx++;
3967 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3968 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3969 file, linenum, args[myidx]);
3970 err_code |= ERR_ALERT | ERR_FATAL;
3971 goto out;
3972 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003973 /* myidx already points to next arg */
3974 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003975 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003976 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003977 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003978
3979 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003980 nw = args[myidx];
3981 while (*nw) {
3982 /* the "store" keyword supports a comma-separated list */
3983 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003984 sa = NULL; /* store arg */
3985 while (*nw && *nw != ',') {
3986 if (*nw == '(') {
3987 *nw = 0;
3988 sa = ++nw;
3989 while (*nw != ')') {
3990 if (!*nw) {
3991 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3992 file, linenum, args[0], cw);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
3996 nw++;
3997 }
3998 *nw = '\0';
3999 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004000 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004001 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004002 if (*nw)
4003 *nw++ = '\0';
4004 type = stktable_get_data_type(cw);
4005 if (type < 0) {
4006 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4007 file, linenum, args[0], cw);
4008 err_code |= ERR_ALERT | ERR_FATAL;
4009 goto out;
4010 }
Willy Tarreauac782882010-06-20 10:41:54 +02004011
4012 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4013 switch (err) {
4014 case PE_NONE: break;
4015 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004016 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4017 file, linenum, args[0], cw);
4018 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004019 break;
4020
4021 case PE_ARG_MISSING:
4022 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4023 file, linenum, args[0], cw);
4024 err_code |= ERR_ALERT | ERR_FATAL;
4025 goto out;
4026
4027 case PE_ARG_NOT_USED:
4028 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4029 file, linenum, args[0], cw);
4030 err_code |= ERR_ALERT | ERR_FATAL;
4031 goto out;
4032
4033 default:
4034 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4035 file, linenum, args[0], cw);
4036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004038 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004039 }
4040 myidx++;
4041 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004042 else {
4043 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4044 file, linenum, args[myidx]);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004047 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004048 }
4049
4050 if (!curproxy->table.size) {
4051 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4052 file, linenum);
4053 err_code |= ERR_ALERT | ERR_FATAL;
4054 goto out;
4055 }
4056
4057 if (curproxy->table.type == (unsigned int)-1) {
4058 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4059 file, linenum);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063 }
4064 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004065 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004066 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004067 int myidx = 0;
4068 const char *name = NULL;
4069 int flags;
4070
4071 if (curproxy == &defproxy) {
4072 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076
4077 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4078 err_code |= ERR_WARN;
4079 goto out;
4080 }
4081
4082 myidx++;
4083 if ((strcmp(args[myidx], "store") == 0) ||
4084 (strcmp(args[myidx], "store-request") == 0)) {
4085 myidx++;
4086 flags = STK_IS_STORE;
4087 }
4088 else if (strcmp(args[myidx], "store-response") == 0) {
4089 myidx++;
4090 flags = STK_IS_STORE | STK_ON_RSP;
4091 }
4092 else if (strcmp(args[myidx], "match") == 0) {
4093 myidx++;
4094 flags = STK_IS_MATCH;
4095 }
4096 else if (strcmp(args[myidx], "on") == 0) {
4097 myidx++;
4098 flags = STK_IS_MATCH | STK_IS_STORE;
4099 }
4100 else {
4101 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4102 err_code |= ERR_ALERT | ERR_FATAL;
4103 goto out;
4104 }
4105
4106 if (*(args[myidx]) == 0) {
4107 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4108 err_code |= ERR_ALERT | ERR_FATAL;
4109 goto out;
4110 }
4111
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004112 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004113 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004114 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004115 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
4119
4120 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004121 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4122 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4123 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004124 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004125 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004126 goto out;
4127 }
4128 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004129 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4130 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4131 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004132 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004133 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004134 goto out;
4135 }
4136 }
4137
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004138 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004139 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004140
Emeric Brunb982a3d2010-01-04 15:45:53 +01004141 if (strcmp(args[myidx], "table") == 0) {
4142 myidx++;
4143 name = args[myidx++];
4144 }
4145
Willy Tarreauef6494c2010-01-28 17:12:36 +01004146 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004147 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4148 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4149 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004150 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004151 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004152 goto out;
4153 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004154 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004155 else if (*(args[myidx])) {
4156 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4157 file, linenum, args[0], args[myidx]);
4158 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004159 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004160 goto out;
4161 }
Emeric Brun97679e72010-09-23 17:56:44 +02004162 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004163 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004164 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004165 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004166
Emeric Brunb982a3d2010-01-04 15:45:53 +01004167 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4168 rule->cond = cond;
4169 rule->expr = expr;
4170 rule->flags = flags;
4171 rule->table.name = name ? strdup(name) : NULL;
4172 LIST_INIT(&rule->list);
4173 if (flags & STK_ON_RSP)
4174 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4175 else
4176 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4177 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 else if (!strcmp(args[0], "stats")) {
4179 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4180 curproxy->uri_auth = NULL; /* we must detach from the default config */
4181
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004182 if (!*args[1]) {
4183 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004184 } else if (!strcmp(args[1], "admin")) {
4185 struct stats_admin_rule *rule;
4186
4187 if (curproxy == &defproxy) {
4188 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4189 err_code |= ERR_ALERT | ERR_FATAL;
4190 goto out;
4191 }
4192
4193 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4194 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4195 err_code |= ERR_ALERT | ERR_ABORT;
4196 goto out;
4197 }
4198
4199 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4200 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4201 file, linenum, args[0], args[1]);
4202 err_code |= ERR_ALERT | ERR_FATAL;
4203 goto out;
4204 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004205 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4206 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4207 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004208 err_code |= ERR_ALERT | ERR_FATAL;
4209 goto out;
4210 }
4211
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004212 err_code |= warnif_cond_conflicts(cond,
4213 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4214 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004215
4216 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4217 rule->cond = cond;
4218 LIST_INIT(&rule->list);
4219 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004220 } else if (!strcmp(args[1], "uri")) {
4221 if (*(args[2]) == 0) {
4222 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004223 err_code |= ERR_ALERT | ERR_FATAL;
4224 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004225 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4226 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004227 err_code |= ERR_ALERT | ERR_ABORT;
4228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004229 }
4230 } else if (!strcmp(args[1], "realm")) {
4231 if (*(args[2]) == 0) {
4232 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004233 err_code |= ERR_ALERT | ERR_FATAL;
4234 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004235 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4236 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004237 err_code |= ERR_ALERT | ERR_ABORT;
4238 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004239 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004240 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004241 unsigned interval;
4242
4243 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4244 if (err) {
4245 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4246 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004247 err_code |= ERR_ALERT | ERR_FATAL;
4248 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004249 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4250 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004251 err_code |= ERR_ALERT | ERR_ABORT;
4252 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004253 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004254 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01004255 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004256
4257 if (curproxy == &defproxy) {
4258 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
4261 }
4262
4263 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4264 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4265 err_code |= ERR_ALERT | ERR_ABORT;
4266 goto out;
4267 }
4268
Willy Tarreauff011f22011-01-06 17:51:27 +01004269 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
4270 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004271 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4272 file, linenum, args[0]);
4273 err_code |= ERR_WARN;
4274 }
4275
Willy Tarreauff011f22011-01-06 17:51:27 +01004276 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004277
Willy Tarreauff011f22011-01-06 17:51:27 +01004278 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004279 err_code |= ERR_ALERT | ERR_ABORT;
4280 goto out;
4281 }
4282
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004283 err_code |= warnif_cond_conflicts(rule->cond,
4284 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4285 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004286 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004287
Willy Tarreaubaaee002006-06-26 02:48:02 +02004288 } else if (!strcmp(args[1], "auth")) {
4289 if (*(args[2]) == 0) {
4290 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004291 err_code |= ERR_ALERT | ERR_FATAL;
4292 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004293 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4294 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004295 err_code |= ERR_ALERT | ERR_ABORT;
4296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004297 }
4298 } else if (!strcmp(args[1], "scope")) {
4299 if (*(args[2]) == 0) {
4300 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004303 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4304 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004305 err_code |= ERR_ALERT | ERR_ABORT;
4306 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004307 }
4308 } else if (!strcmp(args[1], "enable")) {
4309 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4310 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004311 err_code |= ERR_ALERT | ERR_ABORT;
4312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004313 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004314 } else if (!strcmp(args[1], "hide-version")) {
4315 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4316 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004317 err_code |= ERR_ALERT | ERR_ABORT;
4318 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004319 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004320 } else if (!strcmp(args[1], "show-legends")) {
4321 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4322 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4323 err_code |= ERR_ALERT | ERR_ABORT;
4324 goto out;
4325 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004326 } else if (!strcmp(args[1], "show-node")) {
4327
4328 if (*args[2]) {
4329 int i;
4330 char c;
4331
4332 for (i=0; args[2][i]; i++) {
4333 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004334 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4335 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004336 break;
4337 }
4338
4339 if (!i || args[2][i]) {
4340 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4341 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4342 file, linenum, args[0], args[1]);
4343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
4345 }
4346 }
4347
4348 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4349 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4350 err_code |= ERR_ALERT | ERR_ABORT;
4351 goto out;
4352 }
4353 } else if (!strcmp(args[1], "show-desc")) {
4354 char *desc = NULL;
4355
4356 if (*args[2]) {
4357 int i, len=0;
4358 char *d;
4359
Willy Tarreau348acfe2014-04-14 15:00:39 +02004360 for (i = 2; *args[i]; i++)
4361 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004362
4363 desc = d = (char *)calloc(1, len);
4364
Willy Tarreau348acfe2014-04-14 15:00:39 +02004365 d += snprintf(d, desc + len - d, "%s", args[2]);
4366 for (i = 3; *args[i]; i++)
4367 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004368 }
4369
4370 if (!*args[2] && !global.desc)
4371 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4372 file, linenum, args[1]);
4373 else {
4374 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4375 free(desc);
4376 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4377 err_code |= ERR_ALERT | ERR_ABORT;
4378 goto out;
4379 }
4380 free(desc);
4381 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004382 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004383stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004384 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 +01004385 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004386 err_code |= ERR_ALERT | ERR_FATAL;
4387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004388 }
4389 }
4390 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004391 int optnum;
4392
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004393 if (*(args[1]) == '\0') {
4394 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4395 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004398 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004399
4400 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4401 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004402 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4403 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4404 file, linenum, cfg_opts[optnum].name);
4405 err_code |= ERR_ALERT | ERR_FATAL;
4406 goto out;
4407 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004408 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4409 goto out;
4410
Willy Tarreau93893792009-07-23 13:19:11 +02004411 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4412 err_code |= ERR_WARN;
4413 goto out;
4414 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004415
Willy Tarreau3842f002009-06-14 11:39:52 +02004416 curproxy->no_options &= ~cfg_opts[optnum].val;
4417 curproxy->options &= ~cfg_opts[optnum].val;
4418
4419 switch (kwm) {
4420 case KWM_STD:
4421 curproxy->options |= cfg_opts[optnum].val;
4422 break;
4423 case KWM_NO:
4424 curproxy->no_options |= cfg_opts[optnum].val;
4425 break;
4426 case KWM_DEF: /* already cleared */
4427 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004428 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004429
Willy Tarreau93893792009-07-23 13:19:11 +02004430 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004431 }
4432 }
4433
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004434 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4435 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004436 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4437 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4438 file, linenum, cfg_opts2[optnum].name);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004442 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4443 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004444 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4445 err_code |= ERR_WARN;
4446 goto out;
4447 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004448
Willy Tarreau3842f002009-06-14 11:39:52 +02004449 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4450 curproxy->options2 &= ~cfg_opts2[optnum].val;
4451
4452 switch (kwm) {
4453 case KWM_STD:
4454 curproxy->options2 |= cfg_opts2[optnum].val;
4455 break;
4456 case KWM_NO:
4457 curproxy->no_options2 |= cfg_opts2[optnum].val;
4458 break;
4459 case KWM_DEF: /* already cleared */
4460 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004461 }
Willy Tarreau93893792009-07-23 13:19:11 +02004462 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004463 }
4464 }
4465
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004466 /* HTTP options override each other. They can be cancelled using
4467 * "no option xxx" which only switches to default mode if the mode
4468 * was this one (useful for cancelling options set in defaults
4469 * sections).
4470 */
4471 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004472 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4473 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004474 if (kwm == KWM_STD) {
4475 curproxy->options &= ~PR_O_HTTP_MODE;
4476 curproxy->options |= PR_O_HTTP_PCL;
4477 goto out;
4478 }
4479 else if (kwm == KWM_NO) {
4480 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4481 curproxy->options &= ~PR_O_HTTP_MODE;
4482 goto out;
4483 }
4484 }
4485 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004486 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4487 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004488 if (kwm == KWM_STD) {
4489 curproxy->options &= ~PR_O_HTTP_MODE;
4490 curproxy->options |= PR_O_HTTP_FCL;
4491 goto out;
4492 }
4493 else if (kwm == KWM_NO) {
4494 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4495 curproxy->options &= ~PR_O_HTTP_MODE;
4496 goto out;
4497 }
4498 }
4499 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004500 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4501 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004502 if (kwm == KWM_STD) {
4503 curproxy->options &= ~PR_O_HTTP_MODE;
4504 curproxy->options |= PR_O_HTTP_SCL;
4505 goto out;
4506 }
4507 else if (kwm == KWM_NO) {
4508 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4509 curproxy->options &= ~PR_O_HTTP_MODE;
4510 goto out;
4511 }
4512 }
4513 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004514 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4515 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004516 if (kwm == KWM_STD) {
4517 curproxy->options &= ~PR_O_HTTP_MODE;
4518 curproxy->options |= PR_O_HTTP_KAL;
4519 goto out;
4520 }
4521 else if (kwm == KWM_NO) {
4522 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4523 curproxy->options &= ~PR_O_HTTP_MODE;
4524 goto out;
4525 }
4526 }
4527 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004528 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4529 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004530 if (kwm == KWM_STD) {
4531 curproxy->options &= ~PR_O_HTTP_MODE;
4532 curproxy->options |= PR_O_HTTP_TUN;
4533 goto out;
4534 }
4535 else if (kwm == KWM_NO) {
4536 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4537 curproxy->options &= ~PR_O_HTTP_MODE;
4538 goto out;
4539 }
4540 }
4541
Joseph Lynch726ab712015-05-11 23:25:34 -07004542 /* Redispatch can take an integer argument that control when the
4543 * resispatch occurs. All values are relative to the retries option.
4544 * This can be cancelled using "no option xxx".
4545 */
4546 if (strcmp(args[1], "redispatch") == 0) {
4547 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4548 err_code |= ERR_WARN;
4549 goto out;
4550 }
4551
4552 curproxy->no_options &= ~PR_O_REDISP;
4553 curproxy->options &= ~PR_O_REDISP;
4554
4555 switch (kwm) {
4556 case KWM_STD:
4557 curproxy->options |= PR_O_REDISP;
4558 curproxy->redispatch_after = -1;
4559 if(*args[2]) {
4560 curproxy->redispatch_after = atol(args[2]);
4561 }
4562 break;
4563 case KWM_NO:
4564 curproxy->no_options |= PR_O_REDISP;
4565 curproxy->redispatch_after = 0;
4566 break;
4567 case KWM_DEF: /* already cleared */
4568 break;
4569 }
4570 goto out;
4571 }
4572
Willy Tarreau3842f002009-06-14 11:39:52 +02004573 if (kwm != KWM_STD) {
4574 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004575 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004576 err_code |= ERR_ALERT | ERR_FATAL;
4577 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004578 }
4579
Emeric Brun3a058f32009-06-30 18:26:00 +02004580 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004581 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004582 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004583 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004584 if (*(args[2]) != '\0') {
4585 if (!strcmp(args[2], "clf")) {
4586 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004587 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004588 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004589 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004590 err_code |= ERR_ALERT | ERR_FATAL;
4591 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004592 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004593 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4594 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004595 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004596 if (curproxy->conf.logformat_string != default_http_log_format &&
4597 curproxy->conf.logformat_string != default_tcp_log_format &&
4598 curproxy->conf.logformat_string != clf_http_log_format)
4599 free(curproxy->conf.logformat_string);
4600 curproxy->conf.logformat_string = logformat;
4601
4602 free(curproxy->conf.lfs_file);
4603 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4604 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004605 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004606 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004607 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004608 if (curproxy->conf.logformat_string != default_http_log_format &&
4609 curproxy->conf.logformat_string != default_tcp_log_format &&
4610 curproxy->conf.logformat_string != clf_http_log_format)
4611 free(curproxy->conf.logformat_string);
4612 curproxy->conf.logformat_string = default_tcp_log_format;
4613
4614 free(curproxy->conf.lfs_file);
4615 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4616 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004617
4618 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4619 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004621 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004622 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004623 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004624 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004625
William Lallemanddf1425a2015-04-28 20:17:49 +02004626 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4627 goto out;
4628
Willy Tarreau13943ab2006-12-31 00:24:10 +01004629 if (curproxy->cap & PR_CAP_FE)
4630 curproxy->options |= PR_O_TCP_CLI_KA;
4631 if (curproxy->cap & PR_CAP_BE)
4632 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004633 }
4634 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004635 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004636 err_code |= ERR_WARN;
4637
Willy Tarreaubaaee002006-06-26 02:48:02 +02004638 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004639 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004640 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004641 curproxy->options2 &= ~PR_O2_CHK_ANY;
4642 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004643 if (!*args[2]) { /* no argument */
4644 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4645 curproxy->check_len = strlen(DEF_CHECK_REQ);
4646 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004647 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004648 curproxy->check_req = (char *)malloc(reqlen);
4649 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004650 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004651 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004652 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004653 if (*args[4])
4654 reqlen += strlen(args[4]);
4655 else
4656 reqlen += strlen("HTTP/1.0");
4657
4658 curproxy->check_req = (char *)malloc(reqlen);
4659 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004660 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004661 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004662 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4663 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004664 }
4665 else if (!strcmp(args[1], "ssl-hello-chk")) {
4666 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004667 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004668 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004669
Willy Tarreaua534fea2008-08-03 12:19:50 +02004670 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004671 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004672 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004673 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004674
4675 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4676 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004677 }
Willy Tarreau23677902007-05-08 23:50:35 +02004678 else if (!strcmp(args[1], "smtpchk")) {
4679 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004680 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;
4683 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004684
4685 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4686 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4687 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4688 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4689 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4690 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4691 curproxy->check_req = (char *)malloc(reqlen);
4692 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4693 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4694 } else {
4695 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4696 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4697 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4698 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4699 }
4700 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004701 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4702 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004703 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004704 else if (!strcmp(args[1], "pgsql-check")) {
4705 /* use PostgreSQL request to check servers' health */
4706 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4707 err_code |= ERR_WARN;
4708
4709 free(curproxy->check_req);
4710 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004711 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004712 curproxy->options2 |= PR_O2_PGSQL_CHK;
4713
4714 if (*(args[2])) {
4715 int cur_arg = 2;
4716
4717 while (*(args[cur_arg])) {
4718 if (strcmp(args[cur_arg], "user") == 0) {
4719 char * packet;
4720 uint32_t packet_len;
4721 uint32_t pv;
4722
4723 /* suboption header - needs additional argument for it */
4724 if (*(args[cur_arg+1]) == 0) {
4725 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4726 file, linenum, args[0], args[1], args[cur_arg]);
4727 err_code |= ERR_ALERT | ERR_FATAL;
4728 goto out;
4729 }
4730
4731 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4732 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4733 pv = htonl(0x30000); /* protocol version 3.0 */
4734
4735 packet = (char*) calloc(1, packet_len);
4736
4737 memcpy(packet + 4, &pv, 4);
4738
4739 /* copy "user" */
4740 memcpy(packet + 8, "user", 4);
4741
4742 /* copy username */
4743 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4744
4745 free(curproxy->check_req);
4746 curproxy->check_req = packet;
4747 curproxy->check_len = packet_len;
4748
4749 packet_len = htonl(packet_len);
4750 memcpy(packet, &packet_len, 4);
4751 cur_arg += 2;
4752 } else {
4753 /* unknown suboption - catchall */
4754 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4755 file, linenum, args[0], args[1]);
4756 err_code |= ERR_ALERT | ERR_FATAL;
4757 goto out;
4758 }
4759 } /* end while loop */
4760 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004761 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4762 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004763 }
4764
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004765 else if (!strcmp(args[1], "redis-check")) {
4766 /* use REDIS PING request to check servers' health */
4767 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4768 err_code |= ERR_WARN;
4769
4770 free(curproxy->check_req);
4771 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004772 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004773 curproxy->options2 |= PR_O2_REDIS_CHK;
4774
4775 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4776 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4777 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004778
4779 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4780 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004781 }
4782
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004783 else if (!strcmp(args[1], "mysql-check")) {
4784 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004785 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4786 err_code |= ERR_WARN;
4787
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004788 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004789 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004790 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004791 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004792
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004793 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004794 * const char mysql40_client_auth_pkt[] = {
4795 * "\x0e\x00\x00" // packet length
4796 * "\x01" // packet number
4797 * "\x00\x00" // client capabilities
4798 * "\x00\x00\x01" // max packet
4799 * "haproxy\x00" // username (null terminated string)
4800 * "\x00" // filler (always 0x00)
4801 * "\x01\x00\x00" // packet length
4802 * "\x00" // packet number
4803 * "\x01" // COM_QUIT command
4804 * };
4805 */
4806
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004807 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4808 * const char mysql41_client_auth_pkt[] = {
4809 * "\x0e\x00\x00\" // packet length
4810 * "\x01" // packet number
4811 * "\x00\x00\x00\x00" // client capabilities
4812 * "\x00\x00\x00\x01" // max packet
4813 * "\x21" // character set (UTF-8)
4814 * char[23] // All zeroes
4815 * "haproxy\x00" // username (null terminated string)
4816 * "\x00" // filler (always 0x00)
4817 * "\x01\x00\x00" // packet length
4818 * "\x00" // packet number
4819 * "\x01" // COM_QUIT command
4820 * };
4821 */
4822
4823
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004824 if (*(args[2])) {
4825 int cur_arg = 2;
4826
4827 while (*(args[cur_arg])) {
4828 if (strcmp(args[cur_arg], "user") == 0) {
4829 char *mysqluser;
4830 int packetlen, reqlen, userlen;
4831
4832 /* suboption header - needs additional argument for it */
4833 if (*(args[cur_arg+1]) == 0) {
4834 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4835 file, linenum, args[0], args[1], args[cur_arg]);
4836 err_code |= ERR_ALERT | ERR_FATAL;
4837 goto out;
4838 }
4839 mysqluser = args[cur_arg + 1];
4840 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004841
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004842 if (*(args[cur_arg+2])) {
4843 if (!strcmp(args[cur_arg+2], "post-41")) {
4844 packetlen = userlen + 7 + 27;
4845 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004846
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004847 free(curproxy->check_req);
4848 curproxy->check_req = (char *)calloc(1, reqlen);
4849 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004850
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004851 snprintf(curproxy->check_req, 4, "%c%c%c",
4852 ((unsigned char) packetlen & 0xff),
4853 ((unsigned char) (packetlen >> 8) & 0xff),
4854 ((unsigned char) (packetlen >> 16) & 0xff));
4855
4856 curproxy->check_req[3] = 1;
4857 curproxy->check_req[5] = 130;
4858 curproxy->check_req[11] = 1;
4859 curproxy->check_req[12] = 33;
4860 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4861 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4862 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4863 cur_arg += 3;
4864 } else {
4865 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4866 err_code |= ERR_ALERT | ERR_FATAL;
4867 goto out;
4868 }
4869 } else {
4870 packetlen = userlen + 7;
4871 reqlen = packetlen + 9;
4872
4873 free(curproxy->check_req);
4874 curproxy->check_req = (char *)calloc(1, reqlen);
4875 curproxy->check_len = reqlen;
4876
4877 snprintf(curproxy->check_req, 4, "%c%c%c",
4878 ((unsigned char) packetlen & 0xff),
4879 ((unsigned char) (packetlen >> 8) & 0xff),
4880 ((unsigned char) (packetlen >> 16) & 0xff));
4881
4882 curproxy->check_req[3] = 1;
4883 curproxy->check_req[5] = 128;
4884 curproxy->check_req[8] = 1;
4885 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4886 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4887 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4888 cur_arg += 2;
4889 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004890 } else {
4891 /* unknown suboption - catchall */
4892 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4893 file, linenum, args[0], args[1]);
4894 err_code |= ERR_ALERT | ERR_FATAL;
4895 goto out;
4896 }
4897 } /* end while loop */
4898 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004899 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004900 else if (!strcmp(args[1], "ldap-check")) {
4901 /* use LDAP request to check servers' health */
4902 free(curproxy->check_req);
4903 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004904 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004905 curproxy->options2 |= PR_O2_LDAP_CHK;
4906
4907 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4908 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4909 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004910 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4911 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004912 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004913 else if (!strcmp(args[1], "tcp-check")) {
4914 /* use raw TCPCHK send/expect to check servers' health */
4915 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4916 err_code |= ERR_WARN;
4917
4918 free(curproxy->check_req);
4919 curproxy->check_req = NULL;
4920 curproxy->options2 &= ~PR_O2_CHK_ANY;
4921 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004922 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4923 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004924 }
Simon Horman98637e52014-06-20 12:30:16 +09004925 else if (!strcmp(args[1], "external-check")) {
4926 /* excute an external command to check servers' health */
4927 free(curproxy->check_req);
4928 curproxy->check_req = NULL;
4929 curproxy->options2 &= ~PR_O2_CHK_ANY;
4930 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004931 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4932 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004933 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004934 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004935 int cur_arg;
4936
4937 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4938 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004939 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004940
Willy Tarreau87cf5142011-08-19 22:57:24 +02004941 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004942
4943 free(curproxy->fwdfor_hdr_name);
4944 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4945 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4946
4947 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4948 cur_arg = 2;
4949 while (*(args[cur_arg])) {
4950 if (!strcmp(args[cur_arg], "except")) {
4951 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004952 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004953 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4954 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004955 err_code |= ERR_ALERT | ERR_FATAL;
4956 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004957 }
4958 /* flush useless bits */
4959 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004960 cur_arg += 2;
4961 } else if (!strcmp(args[cur_arg], "header")) {
4962 /* suboption header - needs additional argument for it */
4963 if (*(args[cur_arg+1]) == 0) {
4964 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4965 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004968 }
4969 free(curproxy->fwdfor_hdr_name);
4970 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4971 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4972 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004973 } else if (!strcmp(args[cur_arg], "if-none")) {
4974 curproxy->options &= ~PR_O_FF_ALWAYS;
4975 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004976 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004977 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004978 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004979 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004980 err_code |= ERR_ALERT | ERR_FATAL;
4981 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004982 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004983 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004984 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004985 else if (!strcmp(args[1], "originalto")) {
4986 int cur_arg;
4987
4988 /* insert x-original-to field, but not for the IP address listed as an except.
4989 * set default options (ie: bitfield, header name, etc)
4990 */
4991
4992 curproxy->options |= PR_O_ORGTO;
4993
4994 free(curproxy->orgto_hdr_name);
4995 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4996 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4997
Willy Tarreau87cf5142011-08-19 22:57:24 +02004998 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004999 cur_arg = 2;
5000 while (*(args[cur_arg])) {
5001 if (!strcmp(args[cur_arg], "except")) {
5002 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005003 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 +02005004 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5005 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005006 err_code |= ERR_ALERT | ERR_FATAL;
5007 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005008 }
5009 /* flush useless bits */
5010 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5011 cur_arg += 2;
5012 } else if (!strcmp(args[cur_arg], "header")) {
5013 /* suboption header - needs additional argument for it */
5014 if (*(args[cur_arg+1]) == 0) {
5015 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5016 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005017 err_code |= ERR_ALERT | ERR_FATAL;
5018 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005019 }
5020 free(curproxy->orgto_hdr_name);
5021 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5022 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5023 cur_arg += 2;
5024 } else {
5025 /* unknown suboption - catchall */
5026 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5027 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005028 err_code |= ERR_ALERT | ERR_FATAL;
5029 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005030 }
5031 } /* end while loop */
5032 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005033 else {
5034 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005035 err_code |= ERR_ALERT | ERR_FATAL;
5036 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005037 }
Willy Tarreau93893792009-07-23 13:19:11 +02005038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005039 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005040 else if (!strcmp(args[0], "default_backend")) {
5041 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005042 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005043
5044 if (*(args[1]) == 0) {
5045 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005046 err_code |= ERR_ALERT | ERR_FATAL;
5047 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005048 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005049 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005050 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005051
5052 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5053 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005054 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005055 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005056 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005057 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005058
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005059 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5060 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 +01005061 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005063 /* enable reconnections to dispatch */
5064 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005065
5066 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005068 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005069 else if (!strcmp(args[0], "http-check")) {
5070 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005071 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005072
5073 if (strcmp(args[1], "disable-on-404") == 0) {
5074 /* enable a graceful server shutdown on an HTTP 404 response */
5075 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005076 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5077 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005078 }
Willy Tarreauef781042010-01-27 11:53:01 +01005079 else if (strcmp(args[1], "send-state") == 0) {
5080 /* enable emission of the apparent state of a server in HTTP checks */
5081 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005082 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5083 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005084 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005085 else if (strcmp(args[1], "expect") == 0) {
5086 const char *ptr_arg;
5087 int cur_arg;
5088
5089 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5090 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5091 err_code |= ERR_ALERT | ERR_FATAL;
5092 goto out;
5093 }
5094
5095 cur_arg = 2;
5096 /* consider exclamation marks, sole or at the beginning of a word */
5097 while (*(ptr_arg = args[cur_arg])) {
5098 while (*ptr_arg == '!') {
5099 curproxy->options2 ^= PR_O2_EXP_INV;
5100 ptr_arg++;
5101 }
5102 if (*ptr_arg)
5103 break;
5104 cur_arg++;
5105 }
5106 /* now ptr_arg points to the beginning of a word past any possible
5107 * exclamation mark, and cur_arg is the argument which holds this word.
5108 */
5109 if (strcmp(ptr_arg, "status") == 0) {
5110 if (!*(args[cur_arg + 1])) {
5111 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5112 file, linenum, args[0], args[1], ptr_arg);
5113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
5115 }
5116 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005117 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005118 curproxy->expect_str = strdup(args[cur_arg + 1]);
5119 }
5120 else if (strcmp(ptr_arg, "string") == 0) {
5121 if (!*(args[cur_arg + 1])) {
5122 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5123 file, linenum, args[0], args[1], ptr_arg);
5124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
5126 }
5127 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005128 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005129 curproxy->expect_str = strdup(args[cur_arg + 1]);
5130 }
5131 else if (strcmp(ptr_arg, "rstatus") == 0) {
5132 if (!*(args[cur_arg + 1])) {
5133 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5134 file, linenum, args[0], args[1], ptr_arg);
5135 err_code |= ERR_ALERT | ERR_FATAL;
5136 goto out;
5137 }
5138 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005139 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005140 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005141 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005142 free(curproxy->expect_regex);
5143 curproxy->expect_regex = NULL;
5144 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005145 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005146 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5147 error = NULL;
5148 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5149 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5150 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5151 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005152 err_code |= ERR_ALERT | ERR_FATAL;
5153 goto out;
5154 }
5155 }
5156 else if (strcmp(ptr_arg, "rstring") == 0) {
5157 if (!*(args[cur_arg + 1])) {
5158 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5159 file, linenum, args[0], args[1], ptr_arg);
5160 err_code |= ERR_ALERT | ERR_FATAL;
5161 goto out;
5162 }
5163 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005164 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005165 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005166 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005167 free(curproxy->expect_regex);
5168 curproxy->expect_regex = NULL;
5169 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005170 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005171 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5172 error = NULL;
5173 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5174 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5175 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5176 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005177 err_code |= ERR_ALERT | ERR_FATAL;
5178 goto out;
5179 }
5180 }
5181 else {
5182 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5183 file, linenum, args[0], args[1], ptr_arg);
5184 err_code |= ERR_ALERT | ERR_FATAL;
5185 goto out;
5186 }
5187 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005188 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005189 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 +02005190 err_code |= ERR_ALERT | ERR_FATAL;
5191 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005192 }
5193 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005194 else if (!strcmp(args[0], "tcp-check")) {
5195 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5196 err_code |= ERR_WARN;
5197
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005198 if (strcmp(args[1], "comment") == 0) {
5199 int cur_arg;
5200 struct tcpcheck_rule *tcpcheck;
5201
5202 cur_arg = 1;
5203 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5204 tcpcheck->action = TCPCHK_ACT_COMMENT;
5205
5206 if (!*args[cur_arg + 1]) {
5207 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5208 file, linenum, args[cur_arg]);
5209 err_code |= ERR_ALERT | ERR_FATAL;
5210 goto out;
5211 }
5212
5213 tcpcheck->comment = strdup(args[cur_arg + 1]);
5214
5215 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005216 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5217 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005218 }
5219 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005220 const char *ptr_arg;
5221 int cur_arg;
5222 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005223
5224 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005225 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5226 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5227 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5228 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5229 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005230
Willy Tarreau5581c272015-05-13 12:24:53 +02005231 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5232 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5233 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5234 file, linenum);
5235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005237 }
5238
5239 cur_arg = 2;
5240 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5241 tcpcheck->action = TCPCHK_ACT_CONNECT;
5242
5243 /* parsing each parameters to fill up the rule */
5244 while (*(ptr_arg = args[cur_arg])) {
5245 /* tcp port */
5246 if (strcmp(args[cur_arg], "port") == 0) {
5247 if ( (atol(args[cur_arg + 1]) > 65535) ||
5248 (atol(args[cur_arg + 1]) < 1) ){
5249 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5250 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5251 err_code |= ERR_ALERT | ERR_FATAL;
5252 goto out;
5253 }
5254 tcpcheck->port = atol(args[cur_arg + 1]);
5255 cur_arg += 2;
5256 }
5257 /* send proxy protocol */
5258 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5259 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5260 cur_arg++;
5261 }
5262#ifdef USE_OPENSSL
5263 else if (strcmp(args[cur_arg], "ssl") == 0) {
5264 curproxy->options |= PR_O_TCPCHK_SSL;
5265 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5266 cur_arg++;
5267 }
5268#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005269 /* comment for this tcpcheck line */
5270 else if (strcmp(args[cur_arg], "comment") == 0) {
5271 if (!*args[cur_arg + 1]) {
5272 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5273 file, linenum, args[cur_arg]);
5274 err_code |= ERR_ALERT | ERR_FATAL;
5275 goto out;
5276 }
5277 tcpcheck->comment = strdup(args[cur_arg + 1]);
5278 cur_arg += 2;
5279 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005280 else {
5281#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005282 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 +01005283#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005284 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 +01005285#endif /* USE_OPENSSL */
5286 file, linenum, args[0], args[1], args[cur_arg]);
5287 err_code |= ERR_ALERT | ERR_FATAL;
5288 goto out;
5289 }
5290
5291 }
5292
5293 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5294 }
5295 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005296 if (! *(args[2]) ) {
5297 /* SEND string expected */
5298 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5299 file, linenum, args[0], args[1], args[2]);
5300 err_code |= ERR_ALERT | ERR_FATAL;
5301 goto out;
5302 } else {
5303 struct tcpcheck_rule *tcpcheck;
5304
5305 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5306
5307 tcpcheck->action = TCPCHK_ACT_SEND;
5308 tcpcheck->string_len = strlen(args[2]);
5309 tcpcheck->string = strdup(args[2]);
5310 tcpcheck->expect_regex = NULL;
5311
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005312 /* comment for this tcpcheck line */
5313 if (strcmp(args[3], "comment") == 0) {
5314 if (!*args[4]) {
5315 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5316 file, linenum, args[3]);
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320 tcpcheck->comment = strdup(args[4]);
5321 }
5322
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005323 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5324 }
5325 }
5326 else if (strcmp(args[1], "send-binary") == 0) {
5327 if (! *(args[2]) ) {
5328 /* SEND binary string expected */
5329 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5330 file, linenum, args[0], args[1], args[2]);
5331 err_code |= ERR_ALERT | ERR_FATAL;
5332 goto out;
5333 } else {
5334 struct tcpcheck_rule *tcpcheck;
5335 char *err = NULL;
5336
5337 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5338
5339 tcpcheck->action = TCPCHK_ACT_SEND;
5340 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5341 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5342 file, linenum, args[0], args[1], args[2], err);
5343 err_code |= ERR_ALERT | ERR_FATAL;
5344 goto out;
5345 }
5346 tcpcheck->expect_regex = NULL;
5347
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005348 /* comment for this tcpcheck line */
5349 if (strcmp(args[3], "comment") == 0) {
5350 if (!*args[4]) {
5351 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5352 file, linenum, args[3]);
5353 err_code |= ERR_ALERT | ERR_FATAL;
5354 goto out;
5355 }
5356 tcpcheck->comment = strdup(args[4]);
5357 }
5358
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005359 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5360 }
5361 }
5362 else if (strcmp(args[1], "expect") == 0) {
5363 const char *ptr_arg;
5364 int cur_arg;
5365 int inverse = 0;
5366
5367 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5368 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5369 err_code |= ERR_ALERT | ERR_FATAL;
5370 goto out;
5371 }
5372
5373 cur_arg = 2;
5374 /* consider exclamation marks, sole or at the beginning of a word */
5375 while (*(ptr_arg = args[cur_arg])) {
5376 while (*ptr_arg == '!') {
5377 inverse = !inverse;
5378 ptr_arg++;
5379 }
5380 if (*ptr_arg)
5381 break;
5382 cur_arg++;
5383 }
5384 /* now ptr_arg points to the beginning of a word past any possible
5385 * exclamation mark, and cur_arg is the argument which holds this word.
5386 */
5387 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005388 struct tcpcheck_rule *tcpcheck;
5389 char *err = NULL;
5390
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005391 if (!*(args[cur_arg + 1])) {
5392 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5393 file, linenum, args[0], args[1], ptr_arg);
5394 err_code |= ERR_ALERT | ERR_FATAL;
5395 goto out;
5396 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005397
5398 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5399
5400 tcpcheck->action = TCPCHK_ACT_EXPECT;
5401 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5402 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5403 file, linenum, args[0], args[1], args[2], err);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407 tcpcheck->expect_regex = NULL;
5408 tcpcheck->inverse = inverse;
5409
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005410 /* tcpcheck comment */
5411 cur_arg += 2;
5412 if (strcmp(args[cur_arg], "comment") == 0) {
5413 if (!*args[cur_arg + 1]) {
5414 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5415 file, linenum, args[cur_arg + 1]);
5416 err_code |= ERR_ALERT | ERR_FATAL;
5417 goto out;
5418 }
5419 tcpcheck->comment = strdup(args[cur_arg + 1]);
5420 }
5421
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005422 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5423 }
5424 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005425 struct tcpcheck_rule *tcpcheck;
5426
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005427 if (!*(args[cur_arg + 1])) {
5428 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5429 file, linenum, args[0], args[1], ptr_arg);
5430 err_code |= ERR_ALERT | ERR_FATAL;
5431 goto out;
5432 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005433
5434 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5435
5436 tcpcheck->action = TCPCHK_ACT_EXPECT;
5437 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5438 tcpcheck->string = strdup(args[cur_arg + 1]);
5439 tcpcheck->expect_regex = NULL;
5440 tcpcheck->inverse = inverse;
5441
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005442 /* tcpcheck comment */
5443 cur_arg += 2;
5444 if (strcmp(args[cur_arg], "comment") == 0) {
5445 if (!*args[cur_arg + 1]) {
5446 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5447 file, linenum, args[cur_arg + 1]);
5448 err_code |= ERR_ALERT | ERR_FATAL;
5449 goto out;
5450 }
5451 tcpcheck->comment = strdup(args[cur_arg + 1]);
5452 }
5453
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005454 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5455 }
5456 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005457 struct tcpcheck_rule *tcpcheck;
5458
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005459 if (!*(args[cur_arg + 1])) {
5460 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5461 file, linenum, args[0], args[1], ptr_arg);
5462 err_code |= ERR_ALERT | ERR_FATAL;
5463 goto out;
5464 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005465
5466 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5467
5468 tcpcheck->action = TCPCHK_ACT_EXPECT;
5469 tcpcheck->string_len = 0;
5470 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005471 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5472 error = NULL;
5473 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5474 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5475 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5476 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005477 err_code |= ERR_ALERT | ERR_FATAL;
5478 goto out;
5479 }
5480 tcpcheck->inverse = inverse;
5481
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005482 /* tcpcheck comment */
5483 cur_arg += 2;
5484 if (strcmp(args[cur_arg], "comment") == 0) {
5485 if (!*args[cur_arg + 1]) {
5486 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5487 file, linenum, args[cur_arg + 1]);
5488 err_code |= ERR_ALERT | ERR_FATAL;
5489 goto out;
5490 }
5491 tcpcheck->comment = strdup(args[cur_arg + 1]);
5492 }
5493
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005494 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5495 }
5496 else {
5497 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5498 file, linenum, args[0], args[1], ptr_arg);
5499 err_code |= ERR_ALERT | ERR_FATAL;
5500 goto out;
5501 }
5502 }
5503 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005504 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005505 err_code |= ERR_ALERT | ERR_FATAL;
5506 goto out;
5507 }
5508 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005509 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005510 if (curproxy == &defproxy) {
5511 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005512 err_code |= ERR_ALERT | ERR_FATAL;
5513 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005514 }
5515
Willy Tarreaub80c2302007-11-30 20:51:32 +01005516 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005517 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005518
5519 if (strcmp(args[1], "fail") == 0) {
5520 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005521 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005522 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5523 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005524 err_code |= ERR_ALERT | ERR_FATAL;
5525 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005526 }
5527
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005528 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5529 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5530 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005533 }
5534 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5535 }
5536 else {
5537 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005538 err_code |= ERR_ALERT | ERR_FATAL;
5539 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005540 }
5541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005542#ifdef TPROXY
5543 else if (!strcmp(args[0], "transparent")) {
5544 /* enable transparent proxy connections */
5545 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005546 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5547 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005548 }
5549#endif
5550 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005551 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005552 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005553
Willy Tarreaubaaee002006-06-26 02:48:02 +02005554 if (*(args[1]) == 0) {
5555 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005556 err_code |= ERR_ALERT | ERR_FATAL;
5557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005558 }
5559 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005560 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5561 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005562 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005563 else if (!strcmp(args[0], "backlog")) { /* backlog */
5564 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005565 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005566
5567 if (*(args[1]) == 0) {
5568 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005569 err_code |= ERR_ALERT | ERR_FATAL;
5570 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005571 }
5572 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005573 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5574 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005575 }
Willy Tarreau86034312006-12-29 00:10:33 +01005576 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005577 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005578 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005579
Willy Tarreau86034312006-12-29 00:10:33 +01005580 if (*(args[1]) == 0) {
5581 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005582 err_code |= ERR_ALERT | ERR_FATAL;
5583 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005584 }
5585 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005586 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5587 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5590 if (*(args[1]) == 0) {
5591 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005594 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005595 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5596 if (err) {
5597 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5598 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005599 err_code |= ERR_ALERT | ERR_FATAL;
5600 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005601 }
5602 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005603 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
5606 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005607 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005608 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005609 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005610
Willy Tarreaubaaee002006-06-26 02:48:02 +02005611 if (curproxy == &defproxy) {
5612 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005615 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005616 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005617 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005618
Willy Tarreau902636f2013-03-10 19:44:48 +01005619 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005620 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005621 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005622 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005623 goto out;
5624 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005625
5626 proto = protocol_by_family(sk->ss_family);
5627 if (!proto || !proto->connect) {
5628 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5629 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005630 err_code |= ERR_ALERT | ERR_FATAL;
5631 goto out;
5632 }
5633
5634 if (port1 != port2) {
5635 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5636 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005637 err_code |= ERR_ALERT | ERR_FATAL;
5638 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005639 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005640
5641 if (!port1) {
5642 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5643 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005644 err_code |= ERR_ALERT | ERR_FATAL;
5645 goto out;
5646 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005647
William Lallemanddf1425a2015-04-28 20:17:49 +02005648 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5649 goto out;
5650
Willy Tarreaud5191e72010-02-09 20:50:45 +01005651 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005652 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005653 }
5654 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005655 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005656 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005657
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005658 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5659 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005663 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005664 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005665 /**
5666 * The syntax for hash-type config element is
5667 * hash-type {map-based|consistent} [[<algo>] avalanche]
5668 *
5669 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5670 */
5671 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005672
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005673 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5674 err_code |= ERR_WARN;
5675
5676 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005677 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5678 }
5679 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005680 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5681 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005682 else if (strcmp(args[1], "avalanche") == 0) {
5683 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]);
5684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005686 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005687 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005688 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
5691 }
Bhaskar98634f02013-10-29 23:30:51 -04005692
5693 /* set the hash function to use */
5694 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005695 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005696 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005697
5698 /* if consistent with no argument, then avalanche modifier is also applied */
5699 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5700 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005701 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005702 /* set the hash function */
5703 if (!strcmp(args[2], "sdbm")) {
5704 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5705 }
5706 else if (!strcmp(args[2], "djb2")) {
5707 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005708 }
5709 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005710 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005711 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005712 else if (!strcmp(args[2], "crc32")) {
5713 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5714 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005715 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005716 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 -05005717 err_code |= ERR_ALERT | ERR_FATAL;
5718 goto out;
5719 }
5720
5721 /* set the hash modifier */
5722 if (!strcmp(args[3], "avalanche")) {
5723 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5724 }
5725 else if (*args[3]) {
5726 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5727 err_code |= ERR_ALERT | ERR_FATAL;
5728 goto out;
5729 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005730 }
William Lallemanda73203e2012-03-12 12:48:57 +01005731 }
William Lallemanda73203e2012-03-12 12:48:57 +01005732 else if (strcmp(args[0], "unique-id-format") == 0) {
5733 if (!*(args[1])) {
5734 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
5737 }
William Lallemand3203ff42012-11-11 17:30:56 +01005738 if (*(args[2])) {
5739 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5740 err_code |= ERR_ALERT | ERR_FATAL;
5741 goto out;
5742 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005743 free(curproxy->conf.uniqueid_format_string);
5744 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005745
Willy Tarreau62a61232013-04-12 18:13:46 +02005746 free(curproxy->conf.uif_file);
5747 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5748 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005749 }
William Lallemanda73203e2012-03-12 12:48:57 +01005750
5751 else if (strcmp(args[0], "unique-id-header") == 0) {
5752 if (!*(args[1])) {
5753 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5754 err_code |= ERR_ALERT | ERR_FATAL;
5755 goto out;
5756 }
5757 free(curproxy->header_unique_id);
5758 curproxy->header_unique_id = strdup(args[1]);
5759 }
5760
William Lallemand723b73a2012-02-08 16:37:49 +01005761 else if (strcmp(args[0], "log-format") == 0) {
5762 if (!*(args[1])) {
5763 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
5766 }
William Lallemand3203ff42012-11-11 17:30:56 +01005767 if (*(args[2])) {
5768 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
5771 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005772
Willy Tarreau62a61232013-04-12 18:13:46 +02005773 if (curproxy->conf.logformat_string != default_http_log_format &&
5774 curproxy->conf.logformat_string != default_tcp_log_format &&
5775 curproxy->conf.logformat_string != clf_http_log_format)
5776 free(curproxy->conf.logformat_string);
5777 curproxy->conf.logformat_string = strdup(args[1]);
5778
5779 free(curproxy->conf.lfs_file);
5780 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5781 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005782
5783 /* get a chance to improve log-format error reporting by
5784 * reporting the correct line-number when possible.
5785 */
5786 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5787 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5788 file, linenum, curproxy->id);
5789 err_code |= ERR_WARN;
5790 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005791 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005792 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5793 if (*(args[1]) == 0) {
5794 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5795 err_code |= ERR_ALERT | ERR_FATAL;
5796 goto out;
5797 }
5798 free(curproxy->log_tag);
5799 curproxy->log_tag = strdup(args[1]);
5800 }
William Lallemand0f99e342011-10-12 17:50:54 +02005801 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5802 /* delete previous herited or defined syslog servers */
5803 struct logsrv *back;
5804
5805 if (*(args[1]) != 0) {
5806 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5807 err_code |= ERR_ALERT | ERR_FATAL;
5808 goto out;
5809 }
5810
William Lallemand723b73a2012-02-08 16:37:49 +01005811 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5812 LIST_DEL(&tmplogsrv->list);
5813 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005814 }
5815 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005816 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005817 struct logsrv *logsrv;
5818
Willy Tarreaubaaee002006-06-26 02:48:02 +02005819 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005820 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005821 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005822 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005823 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005824 LIST_INIT(&node->list);
5825 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5826 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005827 }
5828 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005829 struct sockaddr_storage *sk;
5830 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005831 int arg = 0;
5832 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005833
5834 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005835
Willy Tarreau18324f52014-06-27 18:10:07 +02005836 /* just after the address, a length may be specified */
5837 if (strcmp(args[arg+2], "len") == 0) {
5838 len = atoi(args[arg+3]);
5839 if (len < 80 || len > 65535) {
5840 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5841 file, linenum, args[arg+3]);
5842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
5844 }
5845 logsrv->maxlen = len;
5846
5847 /* skip these two args */
5848 arg += 2;
5849 }
5850 else
5851 logsrv->maxlen = MAX_SYSLOG_LEN;
5852
5853 if (logsrv->maxlen > global.max_syslog_len) {
5854 global.max_syslog_len = logsrv->maxlen;
5855 logline = realloc(logline, global.max_syslog_len + 1);
5856 }
5857
William Lallemanddf1425a2015-04-28 20:17:49 +02005858 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5859 goto out;
5860
Willy Tarreau18324f52014-06-27 18:10:07 +02005861 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005862 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005863 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005864 err_code |= ERR_ALERT | ERR_FATAL;
5865 goto out;
5866
Willy Tarreaubaaee002006-06-26 02:48:02 +02005867 }
5868
William Lallemand0f99e342011-10-12 17:50:54 +02005869 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005870 if (*(args[arg+3])) {
5871 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005872 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005873 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005874 err_code |= ERR_ALERT | ERR_FATAL;
5875 goto out;
5876
Willy Tarreaubaaee002006-06-26 02:48:02 +02005877 }
5878 }
5879
William Lallemand0f99e342011-10-12 17:50:54 +02005880 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005881 if (*(args[arg+4])) {
5882 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005883 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005884 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005885 err_code |= ERR_ALERT | ERR_FATAL;
5886 goto out;
5887
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005888 }
5889 }
5890
Willy Tarreau902636f2013-03-10 19:44:48 +01005891 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005892 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005893 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005894 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005895 goto out;
5896 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005897
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005898 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005899
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005900 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005901 if (port1 != port2) {
5902 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5903 file, linenum, args[0], args[1]);
5904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
5906 }
5907
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005908 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005909 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005910 }
William Lallemand0f99e342011-10-12 17:50:54 +02005911
5912 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005913 }
5914 else {
5915 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5916 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005917 err_code |= ERR_ALERT | ERR_FATAL;
5918 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005919 }
5920 }
5921 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005922 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005923 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005924 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005925 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005926
Willy Tarreau977b8e42006-12-29 14:19:17 +01005927 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005928 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005929
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005931 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5932 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005935 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005936
5937 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005938 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5939 free(curproxy->conn_src.iface_name);
5940 curproxy->conn_src.iface_name = NULL;
5941 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005942
Willy Tarreau902636f2013-03-10 19:44:48 +01005943 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005944 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005945 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005946 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005947 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005948 goto out;
5949 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005950
5951 proto = protocol_by_family(sk->ss_family);
5952 if (!proto || !proto->connect) {
5953 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005954 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005955 err_code |= ERR_ALERT | ERR_FATAL;
5956 goto out;
5957 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005958
5959 if (port1 != port2) {
5960 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5961 file, linenum, args[0], args[1]);
5962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
5965
Willy Tarreauef9a3602012-12-08 22:29:20 +01005966 curproxy->conn_src.source_addr = *sk;
5967 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005968
5969 cur_arg = 2;
5970 while (*(args[cur_arg])) {
5971 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005972#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5973#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005974 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005975 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5976 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005977 err_code |= ERR_ALERT | ERR_FATAL;
5978 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005979 }
5980#endif
5981 if (!*args[cur_arg + 1]) {
5982 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5983 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005984 err_code |= ERR_ALERT | ERR_FATAL;
5985 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005986 }
5987
5988 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005989 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5990 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005991 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005992 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5993 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005994 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5995 char *name, *end;
5996
5997 name = args[cur_arg+1] + 7;
5998 while (isspace(*name))
5999 name++;
6000
6001 end = name;
6002 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6003 end++;
6004
Willy Tarreauef9a3602012-12-08 22:29:20 +01006005 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6006 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6007 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6008 curproxy->conn_src.bind_hdr_len = end - name;
6009 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6010 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6011 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006012
6013 /* now look for an occurrence number */
6014 while (isspace(*end))
6015 end++;
6016 if (*end == ',') {
6017 end++;
6018 name = end;
6019 if (*end == '-')
6020 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006021 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006022 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006023 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006024 }
6025
Willy Tarreauef9a3602012-12-08 22:29:20 +01006026 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006027 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6028 " occurrences values smaller than %d.\n",
6029 file, linenum, MAX_HDR_HISTORY);
6030 err_code |= ERR_ALERT | ERR_FATAL;
6031 goto out;
6032 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006033 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006034 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006035
Willy Tarreau902636f2013-03-10 19:44:48 +01006036 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006037 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006038 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006039 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006040 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006041 goto out;
6042 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006043
6044 proto = protocol_by_family(sk->ss_family);
6045 if (!proto || !proto->connect) {
6046 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6047 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006048 err_code |= ERR_ALERT | ERR_FATAL;
6049 goto out;
6050 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006051
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006052 if (port1 != port2) {
6053 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6054 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006055 err_code |= ERR_ALERT | ERR_FATAL;
6056 goto out;
6057 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006058 curproxy->conn_src.tproxy_addr = *sk;
6059 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006060 }
6061 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02006062#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006063 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006064#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006065#else /* no TPROXY support */
6066 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006067 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006068 err_code |= ERR_ALERT | ERR_FATAL;
6069 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006070#endif
6071 cur_arg += 2;
6072 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006073 }
6074
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006075 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6076#ifdef SO_BINDTODEVICE
6077 if (!*args[cur_arg + 1]) {
6078 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6079 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006080 err_code |= ERR_ALERT | ERR_FATAL;
6081 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006082 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006083 free(curproxy->conn_src.iface_name);
6084 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6085 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006086 global.last_checks |= LSTCHK_NETADM;
6087#else
6088 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6089 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006090 err_code |= ERR_ALERT | ERR_FATAL;
6091 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006092#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006093 cur_arg += 2;
6094 continue;
6095 }
6096 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006097 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006098 err_code |= ERR_ALERT | ERR_FATAL;
6099 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006100 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006101 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006102 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6103 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6104 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006105 err_code |= ERR_ALERT | ERR_FATAL;
6106 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006107 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006109 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6111 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006112 err_code |= ERR_ALERT | ERR_FATAL;
6113 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006114 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006115
6116 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006117 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006118 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006119 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006121 }
6122 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006123 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006124 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006125 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006126 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128 }
6129 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006130 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006131 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006132 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006133 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006135 }
6136 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006137 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006138 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006139 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006140 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006141 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006142 }
6143 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006144 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006145 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006146 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006147 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006149 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006150 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006151 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006152 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006153 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006154 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006155 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006156 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006157 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006158 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006159 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6160 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006161 err_code |= ERR_ALERT | ERR_FATAL;
6162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006163 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006164
6165 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006166 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006167 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006168 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 }
6171 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006172 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006173 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006174 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006175 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 }
6178 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006179 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006180 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006181 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006182 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006183 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006184 }
6185 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006186 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006187 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006188 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006189 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006190 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006191 }
6192 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006193 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006194 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006195 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006196 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006198 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006199 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006200 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006201 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006202 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006203 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006204 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006205 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006206 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006207 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006208
Willy Tarreaubaaee002006-06-26 02:48:02 +02006209 if (curproxy == &defproxy) {
6210 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006211 err_code |= ERR_ALERT | ERR_FATAL;
6212 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006213 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006214 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006215 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216
Willy Tarreaubaaee002006-06-26 02:48:02 +02006217 if (*(args[1]) == 0) {
6218 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006219 err_code |= ERR_ALERT | ERR_FATAL;
6220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006222
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006223 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006224 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6225 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6226 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006227 err_code |= ERR_ALERT | ERR_FATAL;
6228 goto out;
6229 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006230 err_code |= warnif_cond_conflicts(cond,
6231 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6232 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006233 }
6234 else if (*args[2]) {
6235 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6236 file, linenum, args[0], args[2]);
6237 err_code |= ERR_ALERT | ERR_FATAL;
6238 goto out;
6239 }
6240
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006241 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006242 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006243 wl->s = strdup(args[1]);
6244 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006245 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006246 }
6247 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006248 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006249 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6250 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006251 err_code |= ERR_ALERT | ERR_FATAL;
6252 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006253 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006254
Willy Tarreauade5ec42010-01-28 19:33:49 +01006255 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006256 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006257 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006258 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006259 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006260 }
6261 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006262 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006263 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006264 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006265 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006266 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006267 }
6268 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006269 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006270 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006271 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006272 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006273 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006274 }
6275 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006276 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006281 }
6282
Willy Tarreauade5ec42010-01-28 19:33:49 +01006283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006284 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006285 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006288 }
6289 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006291 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 }
6296 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006298 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 }
6303 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006304 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006305
Willy Tarreaubaaee002006-06-26 02:48:02 +02006306 if (curproxy == &defproxy) {
6307 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006308 err_code |= ERR_ALERT | ERR_FATAL;
6309 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006310 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006311 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006312 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313
Willy Tarreaubaaee002006-06-26 02:48:02 +02006314 if (*(args[1]) == 0) {
6315 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006316 err_code |= ERR_ALERT | ERR_FATAL;
6317 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006318 }
6319
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006320 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006321 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6322 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6323 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006324 err_code |= ERR_ALERT | ERR_FATAL;
6325 goto out;
6326 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006327 err_code |= warnif_cond_conflicts(cond,
6328 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6329 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006330 }
6331 else if (*args[2]) {
6332 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6333 file, linenum, args[0], args[2]);
6334 err_code |= ERR_ALERT | ERR_FATAL;
6335 goto out;
6336 }
6337
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006338 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006339 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006340 wl->s = strdup(args[1]);
6341 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 }
6343 else if (!strcmp(args[0], "errorloc") ||
6344 !strcmp(args[0], "errorloc302") ||
6345 !strcmp(args[0], "errorloc303")) { /* error location */
6346 int errnum, errlen;
6347 char *err;
6348
Willy Tarreau977b8e42006-12-29 14:19:17 +01006349 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006350 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006351
Willy Tarreaubaaee002006-06-26 02:48:02 +02006352 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006353 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006354 err_code |= ERR_ALERT | ERR_FATAL;
6355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006356 }
6357
6358 errnum = atol(args[1]);
6359 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006360 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6361 err = malloc(errlen);
6362 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006363 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006364 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6365 err = malloc(errlen);
6366 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367 }
6368
Willy Tarreau0f772532006-12-23 20:51:41 +01006369 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6370 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006371 chunk_destroy(&curproxy->errmsg[rc]);
6372 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006373 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006376
6377 if (rc >= HTTP_ERR_SIZE) {
6378 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6379 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 free(err);
6381 }
6382 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006383 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6384 int errnum, errlen, fd;
6385 char *err;
6386 struct stat stat;
6387
6388 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006389 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006390
6391 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006392 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006393 err_code |= ERR_ALERT | ERR_FATAL;
6394 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006395 }
6396
6397 fd = open(args[2], O_RDONLY);
6398 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6399 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6400 file, linenum, args[2], args[1]);
6401 if (fd >= 0)
6402 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006403 err_code |= ERR_ALERT | ERR_FATAL;
6404 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006405 }
6406
Willy Tarreau27a674e2009-08-17 07:23:33 +02006407 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006408 errlen = stat.st_size;
6409 } else {
6410 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006411 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006412 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006413 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006414 }
6415
6416 err = malloc(errlen); /* malloc() must succeed during parsing */
6417 errnum = read(fd, err, errlen);
6418 if (errnum != errlen) {
6419 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6420 file, linenum, args[2], args[1]);
6421 close(fd);
6422 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006423 err_code |= ERR_ALERT | ERR_FATAL;
6424 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006425 }
6426 close(fd);
6427
6428 errnum = atol(args[1]);
6429 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6430 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006431 chunk_destroy(&curproxy->errmsg[rc]);
6432 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006433 break;
6434 }
6435 }
6436
6437 if (rc >= HTTP_ERR_SIZE) {
6438 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6439 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006440 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006441 free(err);
6442 }
6443 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006444 else if (!strcmp(args[0], "compression")) {
6445 struct comp *comp;
6446 if (curproxy->comp == NULL) {
6447 comp = calloc(1, sizeof(struct comp));
6448 curproxy->comp = comp;
6449 } else {
6450 comp = curproxy->comp;
6451 }
6452
6453 if (!strcmp(args[1], "algo")) {
6454 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006455 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006456
William Lallemand82fe75c2012-10-23 10:25:10 +02006457 cur_arg = 2;
6458 if (!*args[cur_arg]) {
6459 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6460 file, linenum, args[0]);
6461 err_code |= ERR_ALERT | ERR_FATAL;
6462 goto out;
6463 }
6464 while (*(args[cur_arg])) {
6465 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6466 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6467 file, linenum, args[0], args[cur_arg]);
6468 err_code |= ERR_ALERT | ERR_FATAL;
6469 goto out;
6470 }
William Lallemand552df672012-11-07 13:21:47 +01006471 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6472 curproxy->comp->algos->end(&ctx);
6473 } else {
6474 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6475 file, linenum, args[0], args[cur_arg]);
6476 err_code |= ERR_ALERT | ERR_FATAL;
6477 goto out;
6478 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006479 cur_arg ++;
6480 continue;
6481 }
6482 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006483 else if (!strcmp(args[1], "offload")) {
6484 comp->offload = 1;
6485 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006486 else if (!strcmp(args[1], "type")) {
6487 int cur_arg;
6488 cur_arg = 2;
6489 if (!*args[cur_arg]) {
6490 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6491 file, linenum, args[0]);
6492 err_code |= ERR_ALERT | ERR_FATAL;
6493 goto out;
6494 }
6495 while (*(args[cur_arg])) {
6496 comp_append_type(comp, args[cur_arg]);
6497 cur_arg ++;
6498 continue;
6499 }
6500 }
6501 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006502 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006503 file, linenum, args[0]);
6504 err_code |= ERR_ALERT | ERR_FATAL;
6505 goto out;
6506 }
6507 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006509 struct cfg_kw_list *kwl;
6510 int index;
6511
6512 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6513 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6514 if (kwl->kw[index].section != CFG_LISTEN)
6515 continue;
6516 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6517 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006518 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006519 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006520 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006521 err_code |= ERR_ALERT | ERR_FATAL;
6522 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006523 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006524 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006525 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006526 err_code |= ERR_WARN;
6527 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006528 }
Willy Tarreau93893792009-07-23 13:19:11 +02006529 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006530 }
6531 }
6532 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006533
Willy Tarreau6daf3432008-01-22 16:44:08 +01006534 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006535 err_code |= ERR_ALERT | ERR_FATAL;
6536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
Willy Tarreau93893792009-07-23 13:19:11 +02006538 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006539 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006540 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541}
6542
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006543int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006544cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6545{
6546#ifdef CONFIG_HAP_NS
6547 const char *err;
6548 const char *item = args[0];
6549
6550 if (!strcmp(item, "namespace_list")) {
6551 return 0;
6552 }
6553 else if (!strcmp(item, "namespace")) {
6554 size_t idx = 1;
6555 const char *current;
6556 while (*(current = args[idx++])) {
6557 err = invalid_char(current);
6558 if (err) {
6559 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6560 file, linenum, *err, item, current);
6561 return ERR_ALERT | ERR_FATAL;
6562 }
6563
6564 if (netns_store_lookup(current, strlen(current))) {
6565 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6566 file, linenum, current);
6567 return ERR_ALERT | ERR_FATAL;
6568 }
6569 if (!netns_store_insert(current)) {
6570 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6571 file, linenum, current);
6572 return ERR_ALERT | ERR_FATAL;
6573 }
6574 }
6575 }
6576
6577 return 0;
6578#else
6579 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6580 file, linenum);
6581 return ERR_ALERT | ERR_FATAL;
6582#endif
6583}
6584
6585int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006586cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6587{
6588
6589 int err_code = 0;
6590 const char *err;
6591
6592 if (!strcmp(args[0], "userlist")) { /* new userlist */
6593 struct userlist *newul;
6594
6595 if (!*args[1]) {
6596 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6597 file, linenum, args[0]);
6598 err_code |= ERR_ALERT | ERR_FATAL;
6599 goto out;
6600 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006601 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6602 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006603
6604 err = invalid_char(args[1]);
6605 if (err) {
6606 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6607 file, linenum, *err, args[0], args[1]);
6608 err_code |= ERR_ALERT | ERR_FATAL;
6609 goto out;
6610 }
6611
6612 for (newul = userlist; newul; newul = newul->next)
6613 if (!strcmp(newul->name, args[1])) {
6614 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6615 file, linenum, args[1]);
6616 err_code |= ERR_WARN;
6617 goto out;
6618 }
6619
6620 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6621 if (!newul) {
6622 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6623 err_code |= ERR_ALERT | ERR_ABORT;
6624 goto out;
6625 }
6626
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006627 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006628 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006629 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6630 err_code |= ERR_ALERT | ERR_ABORT;
6631 goto out;
6632 }
6633
6634 newul->next = userlist;
6635 userlist = newul;
6636
6637 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006638 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006639 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006640 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006641
6642 if (!*args[1]) {
6643 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6644 file, linenum, args[0]);
6645 err_code |= ERR_ALERT | ERR_FATAL;
6646 goto out;
6647 }
6648
6649 err = invalid_char(args[1]);
6650 if (err) {
6651 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6652 file, linenum, *err, args[0], args[1]);
6653 err_code |= ERR_ALERT | ERR_FATAL;
6654 goto out;
6655 }
6656
William Lallemand4ac9f542015-05-28 18:03:51 +02006657 if (!userlist)
6658 goto out;
6659
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006660 for (ag = userlist->groups; ag; ag = ag->next)
6661 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006662 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6663 file, linenum, args[1], userlist->name);
6664 err_code |= ERR_ALERT;
6665 goto out;
6666 }
6667
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006668 ag = calloc(1, sizeof(*ag));
6669 if (!ag) {
6670 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6671 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006672 goto out;
6673 }
6674
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006675 ag->name = strdup(args[1]);
6676 if (!ag) {
6677 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6678 err_code |= ERR_ALERT | ERR_ABORT;
6679 goto out;
6680 }
6681
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006682 cur_arg = 2;
6683
6684 while (*args[cur_arg]) {
6685 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006686 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006687 cur_arg += 2;
6688 continue;
6689 } else {
6690 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6691 file, linenum, args[0]);
6692 err_code |= ERR_ALERT | ERR_FATAL;
6693 goto out;
6694 }
6695 }
6696
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006697 ag->next = userlist->groups;
6698 userlist->groups = ag;
6699
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006700 } else if (!strcmp(args[0], "user")) { /* new user */
6701 struct auth_users *newuser;
6702 int cur_arg;
6703
6704 if (!*args[1]) {
6705 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6706 file, linenum, args[0]);
6707 err_code |= ERR_ALERT | ERR_FATAL;
6708 goto out;
6709 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006710 if (!userlist)
6711 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006712
6713 for (newuser = userlist->users; newuser; newuser = newuser->next)
6714 if (!strcmp(newuser->user, args[1])) {
6715 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6716 file, linenum, args[1], userlist->name);
6717 err_code |= ERR_ALERT;
6718 goto out;
6719 }
6720
6721 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6722 if (!newuser) {
6723 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6724 err_code |= ERR_ALERT | ERR_ABORT;
6725 goto out;
6726 }
6727
6728 newuser->user = strdup(args[1]);
6729
6730 newuser->next = userlist->users;
6731 userlist->users = newuser;
6732
6733 cur_arg = 2;
6734
6735 while (*args[cur_arg]) {
6736 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006737#ifdef CONFIG_HAP_CRYPT
6738 if (!crypt("", args[cur_arg + 1])) {
6739 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6740 file, linenum, newuser->user);
6741 err_code |= ERR_ALERT | ERR_FATAL;
6742 goto out;
6743 }
6744#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006745 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6746 file, linenum);
6747 err_code |= ERR_ALERT;
6748#endif
6749 newuser->pass = strdup(args[cur_arg + 1]);
6750 cur_arg += 2;
6751 continue;
6752 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6753 newuser->pass = strdup(args[cur_arg + 1]);
6754 newuser->flags |= AU_O_INSECURE;
6755 cur_arg += 2;
6756 continue;
6757 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006758 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006759 cur_arg += 2;
6760 continue;
6761 } else {
6762 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6763 file, linenum, args[0]);
6764 err_code |= ERR_ALERT | ERR_FATAL;
6765 goto out;
6766 }
6767 }
6768 } else {
6769 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6770 err_code |= ERR_ALERT | ERR_FATAL;
6771 }
6772
6773out:
6774 return err_code;
6775}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006776
6777/*
6778 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006779 * Returns the error code, 0 if OK, or any combination of :
6780 * - ERR_ABORT: must abort ASAP
6781 * - ERR_FATAL: we can continue parsing but not start the service
6782 * - ERR_WARN: a warning has been emitted
6783 * - ERR_ALERT: an alert has been emitted
6784 * Only the two first ones can stop processing, the two others are just
6785 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006786 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006787int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006788{
William Lallemand64e84512015-05-12 14:25:37 +02006789 char *thisline;
6790 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006791 FILE *f;
6792 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006793 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006794 struct cfg_section *cs = NULL;
6795 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006796 int readbytes = 0;
6797
6798 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006799 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006800 return -1;
6801 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006802
6803 /* Register internal sections */
6804 if (!cfg_register_section("listen", cfg_parse_listen) ||
6805 !cfg_register_section("frontend", cfg_parse_listen) ||
6806 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006807 !cfg_register_section("defaults", cfg_parse_listen) ||
6808 !cfg_register_section("global", cfg_parse_global) ||
6809 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006810 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006811 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006812 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6813 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006814 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006815
Willy Tarreaubaaee002006-06-26 02:48:02 +02006816 if ((f=fopen(file,"r")) == NULL)
6817 return -1;
6818
William Lallemandb2f07452015-05-12 14:27:13 +02006819next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006820 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006821 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006822 char *end;
6823 char *args[MAX_LINE_ARGS + 1];
6824 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006825 int dquote = 0; /* double quote */
6826 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006827
Willy Tarreaubaaee002006-06-26 02:48:02 +02006828 linenum++;
6829
6830 end = line + strlen(line);
6831
William Lallemand64e84512015-05-12 14:25:37 +02006832 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006833 /* Check if we reached the limit and the last char is not \n.
6834 * Watch out for the last line without the terminating '\n'!
6835 */
William Lallemand64e84512015-05-12 14:25:37 +02006836 char *newline;
6837 int newlinesize = linesize * 2;
6838
6839 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6840 if (newline == NULL) {
6841 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6842 file, linenum);
6843 err_code |= ERR_ALERT | ERR_FATAL;
6844 continue;
6845 }
6846
6847 readbytes = linesize - 1;
6848 linesize = newlinesize;
6849 thisline = newline;
6850 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006851 }
6852
William Lallemand64e84512015-05-12 14:25:37 +02006853 readbytes = 0;
6854
Willy Tarreaubaaee002006-06-26 02:48:02 +02006855 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006856 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006857 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006858
Willy Tarreaubaaee002006-06-26 02:48:02 +02006859 arg = 0;
6860 args[arg] = line;
6861
6862 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006863 if (*line == '"' && !squote) { /* double quote outside single quotes */
6864 if (dquote)
6865 dquote = 0;
6866 else
6867 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006868 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006869 end--;
6870 }
6871 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6872 if (squote)
6873 squote = 0;
6874 else
6875 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006876 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006877 end--;
6878 }
6879 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006880 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6881 * C equivalent value. Other combinations left unchanged (eg: \1).
6882 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006883 int skip = 0;
6884 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6885 *line = line[1];
6886 skip = 1;
6887 }
6888 else if (line[1] == 'r') {
6889 *line = '\r';
6890 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006891 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006892 else if (line[1] == 'n') {
6893 *line = '\n';
6894 skip = 1;
6895 }
6896 else if (line[1] == 't') {
6897 *line = '\t';
6898 skip = 1;
6899 }
6900 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006901 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006902 unsigned char hex1, hex2;
6903 hex1 = toupper(line[2]) - '0';
6904 hex2 = toupper(line[3]) - '0';
6905 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6906 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6907 *line = (hex1<<4) + hex2;
6908 skip = 3;
6909 }
6910 else {
6911 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006912 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006913 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006914 } else if (line[1] == '"') {
6915 *line = '"';
6916 skip = 1;
6917 } else if (line[1] == '\'') {
6918 *line = '\'';
6919 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006920 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6921 *line = '$';
6922 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006923 }
6924 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006925 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926 end -= skip;
6927 }
6928 line++;
6929 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006930 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006931 /* end of string, end of loop */
6932 *line = 0;
6933 break;
6934 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006935 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006936 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006937 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006938 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006939 line++;
6940 args[++arg] = line;
6941 }
William Lallemandb2f07452015-05-12 14:27:13 +02006942 else if (dquote && *line == '$') {
6943 /* environment variables are evaluated inside double quotes */
6944 char *var_beg;
6945 char *var_end;
6946 char save_char;
6947 char *value;
6948 int val_len;
6949 int newlinesize;
6950 int braces = 0;
6951
6952 var_beg = line + 1;
6953 var_end = var_beg;
6954
6955 if (*var_beg == '{') {
6956 var_beg++;
6957 var_end++;
6958 braces = 1;
6959 }
6960
6961 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6962 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6963 err_code |= ERR_ALERT | ERR_FATAL;
6964 goto next_line; /* skip current line */
6965 }
6966
6967 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6968 var_end++;
6969
6970 save_char = *var_end;
6971 *var_end = '\0';
6972 value = getenv(var_beg);
6973 *var_end = save_char;
6974 val_len = value ? strlen(value) : 0;
6975
6976 if (braces) {
6977 if (*var_end == '}') {
6978 var_end++;
6979 braces = 0;
6980 } else {
6981 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6982 err_code |= ERR_ALERT | ERR_FATAL;
6983 goto next_line; /* skip current line */
6984 }
6985 }
6986
6987 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6988
6989 /* if not enough space in thisline */
6990 if (newlinesize > linesize) {
6991 char *newline;
6992
6993 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6994 if (newline == NULL) {
6995 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6996 err_code |= ERR_ALERT | ERR_FATAL;
6997 goto next_line; /* slip current line */
6998 }
6999 /* recompute pointers if realloc returns a new pointer */
7000 if (newline != thisline) {
7001 int i;
7002 int diff;
7003
7004 for (i = 0; i <= arg; i++) {
7005 diff = args[i] - thisline;
7006 args[i] = newline + diff;
7007 }
7008
7009 diff = var_end - thisline;
7010 var_end = newline + diff;
7011 diff = end - thisline;
7012 end = newline + diff;
7013 diff = line - thisline;
7014 line = newline + diff;
7015 thisline = newline;
7016 }
7017 linesize = newlinesize;
7018 }
7019
7020 /* insert value inside the line */
7021 memmove(line + val_len, var_end, end - var_end + 1);
7022 memcpy(line, value, val_len);
7023 end += val_len - (var_end - line);
7024 line += val_len;
7025 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007026 else {
7027 line++;
7028 }
7029 }
William Lallemandb2f07452015-05-12 14:27:13 +02007030
William Lallemandf9873ba2015-05-05 17:37:14 +02007031 if (dquote) {
7032 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7033 err_code |= ERR_ALERT | ERR_FATAL;
7034 }
7035
7036 if (squote) {
7037 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7038 err_code |= ERR_ALERT | ERR_FATAL;
7039 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007040
7041 /* empty line */
7042 if (!**args)
7043 continue;
7044
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007045 if (*line) {
7046 /* we had to stop due to too many args.
7047 * Let's terminate the string, print the offending part then cut the
7048 * last arg.
7049 */
7050 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7051 line++;
7052 *line = '\0';
7053
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007054 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007055 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007056 err_code |= ERR_ALERT | ERR_FATAL;
7057 args[arg] = line;
7058 }
7059
Willy Tarreau540abe42007-05-02 20:50:16 +02007060 /* zero out remaining args and ensure that at least one entry
7061 * is zeroed out.
7062 */
7063 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007064 args[arg] = line;
7065 }
7066
Willy Tarreau3842f002009-06-14 11:39:52 +02007067 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007068 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007069 char *tmp;
7070
Willy Tarreau3842f002009-06-14 11:39:52 +02007071 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007072 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007073 for (arg=0; *args[arg+1]; arg++)
7074 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007075 *tmp = '\0'; // fix the next arg to \0
7076 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007077 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007078 else if (!strcmp(args[0], "default")) {
7079 kwm = KWM_DEF;
7080 for (arg=0; *args[arg+1]; arg++)
7081 args[arg] = args[arg+1]; // shift args after inversion
7082 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007083
William Lallemand0f99e342011-10-12 17:50:54 +02007084 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7085 strcmp(args[0], "log") != 0) {
7086 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007087 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007088 }
7089
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007090 /* detect section start */
7091 list_for_each_entry(ics, &sections, list) {
7092 if (strcmp(args[0], ics->section_name) == 0) {
7093 cursection = ics->section_name;
7094 cs = ics;
7095 break;
7096 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007097 }
7098
Willy Tarreaubaaee002006-06-26 02:48:02 +02007099 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007100 if (cs)
7101 err_code |= cs->section_parser(file, linenum, args, kwm);
7102 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007103 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007104 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007105 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007106
7107 if (err_code & ERR_ABORT)
7108 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007109 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007110 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007111 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007112 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007113 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007114}
7115
Willy Tarreau64ab6072014-09-16 12:17:36 +02007116/* This function propagates processes from frontend <from> to backend <to> so
7117 * that it is always guaranteed that a backend pointed to by a frontend is
7118 * bound to all of its processes. After that, if the target is a "listen"
7119 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007120 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007121 * checked first to ensure that <to> is already bound to all processes of
7122 * <from>, there is no risk of looping and we ensure to follow the shortest
7123 * path to the destination.
7124 *
7125 * It is possible to set <to> to NULL for the first call so that the function
7126 * takes care of visiting the initial frontend in <from>.
7127 *
7128 * It is important to note that the function relies on the fact that all names
7129 * have already been resolved.
7130 */
7131void propagate_processes(struct proxy *from, struct proxy *to)
7132{
7133 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007134
7135 if (to) {
7136 /* check whether we need to go down */
7137 if (from->bind_proc &&
7138 (from->bind_proc & to->bind_proc) == from->bind_proc)
7139 return;
7140
7141 if (!from->bind_proc && !to->bind_proc)
7142 return;
7143
7144 to->bind_proc = from->bind_proc ?
7145 (to->bind_proc | from->bind_proc) : 0;
7146
7147 /* now propagate down */
7148 from = to;
7149 }
7150
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007151 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007152 return;
7153
Willy Tarreauf6b70012014-12-18 14:00:43 +01007154 if (from->state == PR_STSTOPPED)
7155 return;
7156
Willy Tarreau64ab6072014-09-16 12:17:36 +02007157 /* default_backend */
7158 if (from->defbe.be)
7159 propagate_processes(from, from->defbe.be);
7160
7161 /* use_backend */
7162 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007163 if (rule->dynamic)
7164 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007165 to = rule->be.backend;
7166 propagate_processes(from, to);
7167 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007168}
7169
Willy Tarreaubb925012009-07-23 13:36:36 +02007170/*
7171 * Returns the error code, 0 if OK, or any combination of :
7172 * - ERR_ABORT: must abort ASAP
7173 * - ERR_FATAL: we can continue parsing but not start the service
7174 * - ERR_WARN: a warning has been emitted
7175 * - ERR_ALERT: an alert has been emitted
7176 * Only the two first ones can stop processing, the two others are just
7177 * indicators.
7178 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007179int check_config_validity()
7180{
7181 int cfgerr = 0;
7182 struct proxy *curproxy = NULL;
7183 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007184 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007185 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007186 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007187
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007188 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007189 /*
7190 * Now, check for the integrity of all that we have collected.
7191 */
7192
7193 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007194 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007195
Willy Tarreau193b8c62012-11-22 00:17:38 +01007196 if (!global.tune.max_http_hdr)
7197 global.tune.max_http_hdr = MAX_HTTP_HDR;
7198
7199 if (!global.tune.cookie_len)
7200 global.tune.cookie_len = CAPTURE_LEN;
7201
7202 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7203
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007204 /* Post initialisation of the users and groups lists. */
7205 err_code = userlist_postinit();
7206 if (err_code != ERR_NONE)
7207 goto out;
7208
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007209 /* first, we will invert the proxy list order */
7210 curproxy = NULL;
7211 while (proxy) {
7212 struct proxy *next;
7213
7214 next = proxy->next;
7215 proxy->next = curproxy;
7216 curproxy = proxy;
7217 if (!next)
7218 break;
7219 proxy = next;
7220 }
7221
Willy Tarreau419ead82014-09-16 13:41:21 +02007222 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007223 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007224 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007225 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007226 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02007227 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007228 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007229 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007230
Willy Tarreau050536d2012-10-04 08:47:34 +02007231 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007232 /* proxy ID not set, use automatic numbering with first
7233 * spare entry starting with next_pxid.
7234 */
7235 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7236 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7237 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007238 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007239 next_pxid++;
7240
Willy Tarreau55ea7572007-06-17 19:56:27 +02007241
Willy Tarreaubaaee002006-06-26 02:48:02 +02007242 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007243 /* ensure we don't keep listeners uselessly bound */
7244 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007245 free((void *)curproxy->table.peers.name);
7246 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 continue;
7248 }
7249
Willy Tarreau102df612014-05-07 23:56:38 +02007250 /* Check multi-process mode compatibility for the current proxy */
7251
7252 if (curproxy->bind_proc) {
7253 /* an explicit bind-process was specified, let's check how many
7254 * processes remain.
7255 */
7256 nbproc = popcount(curproxy->bind_proc);
7257
7258 curproxy->bind_proc &= nbits(global.nbproc);
7259 if (!curproxy->bind_proc && nbproc == 1) {
7260 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);
7261 curproxy->bind_proc = 1;
7262 }
7263 else if (!curproxy->bind_proc && nbproc > 1) {
7264 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);
7265 curproxy->bind_proc = 0;
7266 }
7267 }
7268
Willy Tarreau3d209582014-05-09 17:06:11 +02007269 /* check and reduce the bind-proc of each listener */
7270 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7271 unsigned long mask;
7272
7273 if (!bind_conf->bind_proc)
7274 continue;
7275
7276 mask = nbits(global.nbproc);
7277 if (curproxy->bind_proc)
7278 mask &= curproxy->bind_proc;
7279 /* mask cannot be null here thanks to the previous checks */
7280
7281 nbproc = popcount(bind_conf->bind_proc);
7282 bind_conf->bind_proc &= mask;
7283
7284 if (!bind_conf->bind_proc && nbproc == 1) {
7285 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",
7286 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7287 bind_conf->bind_proc = mask & ~(mask - 1);
7288 }
7289 else if (!bind_conf->bind_proc && nbproc > 1) {
7290 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",
7291 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7292 bind_conf->bind_proc = 0;
7293 }
7294 }
7295
Willy Tarreauff01a212009-03-15 13:46:16 +01007296 switch (curproxy->mode) {
7297 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007298 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007299 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007300 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7301 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007302 cfgerr++;
7303 }
7304
7305 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007306 Warning("config : servers will be ignored for %s '%s'.\n",
7307 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007308 break;
7309
7310 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007311 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007312 break;
7313
7314 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007315 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007316 break;
7317 }
7318
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007319 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007320 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007321 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007322 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7323 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007324 cfgerr++;
7325 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007326#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007327 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007328 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7329 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007330 cfgerr++;
7331 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007332#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007333 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007334 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7335 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007336 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007337 }
7338 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007339 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007340 /* If no LB algo is set in a backend, and we're not in
7341 * transparent mode, dispatch mode nor proxy mode, we
7342 * want to use balance roundrobin by default.
7343 */
7344 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7345 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007346 }
7347 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007348
Willy Tarreau1620ec32011-08-06 17:05:02 +02007349 if (curproxy->options & PR_O_DISPATCH)
7350 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7351 else if (curproxy->options & PR_O_HTTP_PROXY)
7352 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7353 else if (curproxy->options & PR_O_TRANSP)
7354 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007355
Willy Tarreau1620ec32011-08-06 17:05:02 +02007356 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7357 if (curproxy->options & PR_O_DISABLE404) {
7358 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7359 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7360 err_code |= ERR_WARN;
7361 curproxy->options &= ~PR_O_DISABLE404;
7362 }
7363 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7364 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7365 "send-state", proxy_type_str(curproxy), curproxy->id);
7366 err_code |= ERR_WARN;
7367 curproxy->options &= ~PR_O2_CHK_SNDST;
7368 }
Willy Tarreauef781042010-01-27 11:53:01 +01007369 }
7370
Simon Horman98637e52014-06-20 12:30:16 +09007371 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7372 if (!global.external_check) {
7373 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7374 curproxy->id, "option external-check");
7375 cfgerr++;
7376 }
7377 if (!curproxy->check_command) {
7378 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7379 curproxy->id, "option external-check");
7380 cfgerr++;
7381 }
7382 }
7383
Simon Horman64e34162015-02-06 11:11:57 +09007384 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007385 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7386 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09007387 "'email-alert from', 'email-alert level' 'email-alert mailer', "
7388 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007389 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
7390 "to be present).\n",
7391 proxy_type_str(curproxy), curproxy->id);
7392 err_code |= ERR_WARN;
7393 free_email_alert(curproxy);
7394 }
7395 if (!curproxy->email_alert.myhostname)
7396 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007397 }
7398
Simon Horman98637e52014-06-20 12:30:16 +09007399 if (curproxy->check_command) {
7400 int clear = 0;
7401 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7402 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7403 "external-check command", proxy_type_str(curproxy), curproxy->id);
7404 err_code |= ERR_WARN;
7405 clear = 1;
7406 }
7407 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7408 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7409 curproxy->id, "external-check command");
7410 cfgerr++;
7411 }
7412 if (clear) {
7413 free(curproxy->check_command);
7414 curproxy->check_command = NULL;
7415 }
7416 }
7417
7418 if (curproxy->check_path) {
7419 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7420 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7421 "external-check path", proxy_type_str(curproxy), curproxy->id);
7422 err_code |= ERR_WARN;
7423 free(curproxy->check_path);
7424 curproxy->check_path = NULL;
7425 }
7426 }
7427
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007428 /* if a default backend was specified, let's find it */
7429 if (curproxy->defbe.name) {
7430 struct proxy *target;
7431
Willy Tarreauafb39922015-05-26 12:04:09 +02007432 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007433 if (!target) {
7434 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7435 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007436 cfgerr++;
7437 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007438 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7439 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007440 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007441 } else if (target->mode != curproxy->mode &&
7442 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7443
7444 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7445 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7446 curproxy->conf.file, curproxy->conf.line,
7447 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7448 target->conf.file, target->conf.line);
7449 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007450 } else {
7451 free(curproxy->defbe.name);
7452 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007453
7454 /* Emit a warning if this proxy also has some servers */
7455 if (curproxy->srv) {
7456 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7457 curproxy->id);
7458 err_code |= ERR_WARN;
7459 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007460 }
7461 }
7462
Willy Tarreau55ea7572007-06-17 19:56:27 +02007463 /* find the target proxy for 'use_backend' rules */
7464 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007465 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007466 struct logformat_node *node;
7467 char *pxname;
7468
7469 /* Try to parse the string as a log format expression. If the result
7470 * of the parsing is only one entry containing a simple string, then
7471 * it's a standard string corresponding to a static rule, thus the
7472 * parsing is cancelled and be.name is restored to be resolved.
7473 */
7474 pxname = rule->be.name;
7475 LIST_INIT(&rule->be.expr);
7476 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7477 curproxy->conf.args.file, curproxy->conf.args.line);
7478 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7479
7480 if (!LIST_ISEMPTY(&rule->be.expr)) {
7481 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7482 rule->dynamic = 1;
7483 free(pxname);
7484 continue;
7485 }
7486 /* simple string: free the expression and fall back to static rule */
7487 free(node->arg);
7488 free(node);
7489 }
7490
7491 rule->dynamic = 0;
7492 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007493
Willy Tarreauafb39922015-05-26 12:04:09 +02007494 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007495 if (!target) {
7496 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7497 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007498 cfgerr++;
7499 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007500 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7501 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007502 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007503 } else if (target->mode != curproxy->mode &&
7504 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7505
7506 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7507 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7508 curproxy->conf.file, curproxy->conf.line,
7509 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7510 target->conf.file, target->conf.line);
7511 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007512 } else {
7513 free((void *)rule->be.name);
7514 rule->be.backend = target;
7515 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007516 }
7517
Willy Tarreau64ab6072014-09-16 12:17:36 +02007518 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007519 list_for_each_entry(srule, &curproxy->server_rules, list) {
7520 struct server *target = findserver(curproxy, srule->srv.name);
7521
7522 if (!target) {
7523 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7524 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7525 cfgerr++;
7526 continue;
7527 }
7528 free((void *)srule->srv.name);
7529 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007530 }
7531
Emeric Brunb982a3d2010-01-04 15:45:53 +01007532 /* find the target table for 'stick' rules */
7533 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7534 struct proxy *target;
7535
Emeric Brun1d33b292010-01-04 15:47:17 +01007536 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7537 if (mrule->flags & STK_IS_STORE)
7538 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7539
Emeric Brunb982a3d2010-01-04 15:45:53 +01007540 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007541 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007542 else
7543 target = curproxy;
7544
7545 if (!target) {
7546 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7547 curproxy->id, mrule->table.name);
7548 cfgerr++;
7549 }
7550 else if (target->table.size == 0) {
7551 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7552 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7553 cfgerr++;
7554 }
Willy Tarreau12785782012-04-27 21:37:17 +02007555 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7556 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007557 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7558 cfgerr++;
7559 }
7560 else {
7561 free((void *)mrule->table.name);
7562 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007563 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007564 }
7565 }
7566
7567 /* find the target table for 'store response' rules */
7568 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7569 struct proxy *target;
7570
Emeric Brun1d33b292010-01-04 15:47:17 +01007571 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7572
Emeric Brunb982a3d2010-01-04 15:45:53 +01007573 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007574 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007575 else
7576 target = curproxy;
7577
7578 if (!target) {
7579 Alert("Proxy '%s': unable to find store table '%s'.\n",
7580 curproxy->id, mrule->table.name);
7581 cfgerr++;
7582 }
7583 else if (target->table.size == 0) {
7584 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7585 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7586 cfgerr++;
7587 }
Willy Tarreau12785782012-04-27 21:37:17 +02007588 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7589 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007590 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7591 cfgerr++;
7592 }
7593 else {
7594 free((void *)mrule->table.name);
7595 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007596 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007597 }
7598 }
7599
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007600 /* find the target table for 'tcp-request' layer 4 rules */
7601 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7602 struct proxy *target;
7603
Willy Tarreaub4c84932013-07-23 19:15:30 +02007604 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007605 continue;
7606
7607 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007608 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007609 else
7610 target = curproxy;
7611
7612 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007613 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7614 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007615 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007616 cfgerr++;
7617 }
7618 else if (target->table.size == 0) {
7619 Alert("Proxy '%s': table '%s' used but not configured.\n",
7620 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7621 cfgerr++;
7622 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007623 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7624 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7625 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007626 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007627 cfgerr++;
7628 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007629 else {
7630 free(trule->act_prm.trk_ctr.table.n);
7631 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007632 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007633 * to pass a list of counters to track and allocate them right here using
7634 * stktable_alloc_data_type().
7635 */
7636 }
7637 }
7638
Willy Tarreaud1f96522010-08-03 19:34:32 +02007639 /* find the target table for 'tcp-request' layer 6 rules */
7640 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7641 struct proxy *target;
7642
Willy Tarreaub4c84932013-07-23 19:15:30 +02007643 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007644 continue;
7645
7646 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007647 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007648 else
7649 target = curproxy;
7650
7651 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007652 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7653 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007654 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007655 cfgerr++;
7656 }
7657 else if (target->table.size == 0) {
7658 Alert("Proxy '%s': table '%s' used but not configured.\n",
7659 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7660 cfgerr++;
7661 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007662 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7663 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7664 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007665 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007666 cfgerr++;
7667 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007668 else {
7669 free(trule->act_prm.trk_ctr.table.n);
7670 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007671 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007672 * to pass a list of counters to track and allocate them right here using
7673 * stktable_alloc_data_type().
7674 */
7675 }
7676 }
7677
Willy Tarreau09448f72014-06-25 18:12:15 +02007678 /* find the target table for 'http-request' layer 7 rules */
7679 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7680 struct proxy *target;
7681
7682 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7683 continue;
7684
7685 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007686 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007687 else
7688 target = curproxy;
7689
7690 if (!target) {
7691 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7692 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7693 http_req_trk_idx(hrqrule->action));
7694 cfgerr++;
7695 }
7696 else if (target->table.size == 0) {
7697 Alert("Proxy '%s': table '%s' used but not configured.\n",
7698 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7699 cfgerr++;
7700 }
7701 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7702 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7703 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7704 http_req_trk_idx(hrqrule->action));
7705 cfgerr++;
7706 }
7707 else {
7708 free(hrqrule->act_prm.trk_ctr.table.n);
7709 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7710 /* Note: if we decide to enhance the track-sc syntax, we may be able
7711 * to pass a list of counters to track and allocate them right here using
7712 * stktable_alloc_data_type().
7713 */
7714 }
7715 }
7716
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007717 /* move any "block" rules at the beginning of the http-request rules */
7718 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7719 /* insert block_rules into http_req_rules at the beginning */
7720 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7721 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7722 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7723 curproxy->http_req_rules.n = curproxy->block_rules.n;
7724 LIST_INIT(&curproxy->block_rules);
7725 }
7726
Emeric Brun32da3c42010-09-23 18:39:19 +02007727 if (curproxy->table.peers.name) {
7728 struct peers *curpeers = peers;
7729
7730 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7731 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7732 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007733 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007734 break;
7735 }
7736 }
7737
7738 if (!curpeers) {
7739 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7740 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007741 free((void *)curproxy->table.peers.name);
7742 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007743 cfgerr++;
7744 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007745 else if (curpeers->state == PR_STSTOPPED) {
7746 /* silently disable this peers section */
7747 curproxy->table.peers.p = NULL;
7748 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007749 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007750 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7751 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007752 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007753 cfgerr++;
7754 }
7755 }
7756
Simon Horman9dc49962015-01-30 11:22:59 +09007757
7758 if (curproxy->email_alert.mailers.name) {
7759 struct mailers *curmailers = mailers;
7760
7761 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7762 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7763 free(curproxy->email_alert.mailers.name);
7764 curproxy->email_alert.mailers.m = curmailers;
7765 curmailers->users++;
7766 break;
7767 }
7768 }
7769
7770 if (!curmailers) {
7771 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7772 curproxy->id, curproxy->email_alert.mailers.name);
7773 free_email_alert(curproxy);
7774 cfgerr++;
7775 }
7776 }
7777
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007778 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007779 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007780 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7781 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7782 "proxy", curproxy->id);
7783 cfgerr++;
7784 goto out_uri_auth_compat;
7785 }
7786
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007787 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007788 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007789 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007790 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007791
Willy Tarreau95fa4692010-02-01 13:05:50 +01007792 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7793 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007794
7795 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007796 uri_auth_compat_req[i++] = "realm";
7797 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7798 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007799
Willy Tarreau95fa4692010-02-01 13:05:50 +01007800 uri_auth_compat_req[i++] = "unless";
7801 uri_auth_compat_req[i++] = "{";
7802 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7803 uri_auth_compat_req[i++] = "}";
7804 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007805
Willy Tarreauff011f22011-01-06 17:51:27 +01007806 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7807 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007808 cfgerr++;
7809 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007810 }
7811
Willy Tarreauff011f22011-01-06 17:51:27 +01007812 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007813
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007814 if (curproxy->uri_auth->auth_realm) {
7815 free(curproxy->uri_auth->auth_realm);
7816 curproxy->uri_auth->auth_realm = NULL;
7817 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007818
7819 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007820 }
7821out_uri_auth_compat:
7822
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007823 /* compile the log format */
7824 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007825 if (curproxy->conf.logformat_string != default_http_log_format &&
7826 curproxy->conf.logformat_string != default_tcp_log_format &&
7827 curproxy->conf.logformat_string != clf_http_log_format)
7828 free(curproxy->conf.logformat_string);
7829 curproxy->conf.logformat_string = NULL;
7830 free(curproxy->conf.lfs_file);
7831 curproxy->conf.lfs_file = NULL;
7832 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007833 }
7834
Willy Tarreau62a61232013-04-12 18:13:46 +02007835 if (curproxy->conf.logformat_string) {
7836 curproxy->conf.args.ctx = ARGC_LOG;
7837 curproxy->conf.args.file = curproxy->conf.lfs_file;
7838 curproxy->conf.args.line = curproxy->conf.lfs_line;
7839 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007840 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007841 curproxy->conf.args.file = NULL;
7842 curproxy->conf.args.line = 0;
7843 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007844
Willy Tarreau62a61232013-04-12 18:13:46 +02007845 if (curproxy->conf.uniqueid_format_string) {
7846 curproxy->conf.args.ctx = ARGC_UIF;
7847 curproxy->conf.args.file = curproxy->conf.uif_file;
7848 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007849 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007850 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007851 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007852 curproxy->conf.args.file = NULL;
7853 curproxy->conf.args.line = 0;
7854 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007855
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007856 /* only now we can check if some args remain unresolved.
7857 * This must be done after the users and groups resolution.
7858 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007859 cfgerr += smp_resolve_args(curproxy);
7860 if (!cfgerr)
7861 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007862
Willy Tarreau2738a142006-07-08 17:28:09 +02007863 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007864 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007865 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007866 (!curproxy->timeout.connect ||
7867 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007868 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007869 " | While not properly invalid, you will certainly encounter various problems\n"
7870 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007871 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007872 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007873 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007874 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007875
Willy Tarreau1fa31262007-12-03 00:36:16 +01007876 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7877 * We must still support older configurations, so let's find out whether those
7878 * parameters have been set or must be copied from contimeouts.
7879 */
7880 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007881 if (!curproxy->timeout.tarpit ||
7882 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007883 /* tarpit timeout not set. We search in the following order:
7884 * default.tarpit, curr.connect, default.connect.
7885 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007886 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007887 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007888 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007889 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007890 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007891 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007892 }
7893 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007894 (!curproxy->timeout.queue ||
7895 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007896 /* queue timeout not set. We search in the following order:
7897 * default.queue, curr.connect, default.connect.
7898 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007899 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007900 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007901 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007902 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007903 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007904 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007905 }
7906 }
7907
Willy Tarreau1620ec32011-08-06 17:05:02 +02007908 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007909 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7910 curproxy->check_req = (char *)malloc(curproxy->check_len);
7911 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007912 }
7913
Willy Tarreau215663d2014-06-13 18:30:23 +02007914 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7915 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7916 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7917 proxy_type_str(curproxy), curproxy->id);
7918 err_code |= ERR_WARN;
7919 }
7920
Willy Tarreau193b8c62012-11-22 00:17:38 +01007921 /* ensure that cookie capture length is not too large */
7922 if (curproxy->capture_len >= global.tune.cookie_len) {
7923 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7924 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7925 err_code |= ERR_WARN;
7926 curproxy->capture_len = global.tune.cookie_len - 1;
7927 }
7928
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007929 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007930 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007931 curproxy->req_cap_pool = create_pool("ptrcap",
7932 curproxy->nb_req_cap * sizeof(char *),
7933 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007934 }
7935
7936 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007937 curproxy->rsp_cap_pool = create_pool("ptrcap",
7938 curproxy->nb_rsp_cap * sizeof(char *),
7939 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007940 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007941
Willy Tarreaubaaee002006-06-26 02:48:02 +02007942 /* first, we will invert the servers list order */
7943 newsrv = NULL;
7944 while (curproxy->srv) {
7945 struct server *next;
7946
7947 next = curproxy->srv->next;
7948 curproxy->srv->next = newsrv;
7949 newsrv = curproxy->srv;
7950 if (!next)
7951 break;
7952 curproxy->srv = next;
7953 }
7954
Willy Tarreau17edc812014-01-03 12:14:34 +01007955 /* Check that no server name conflicts. This causes trouble in the stats.
7956 * We only emit a warning for the first conflict affecting each server,
7957 * in order to avoid combinatory explosion if all servers have the same
7958 * name. We do that only for servers which do not have an explicit ID,
7959 * because these IDs were made also for distinguishing them and we don't
7960 * want to annoy people who correctly manage them.
7961 */
7962 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7963 struct server *other_srv;
7964
7965 if (newsrv->puid)
7966 continue;
7967
7968 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7969 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7970 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7971 newsrv->conf.file, newsrv->conf.line,
7972 proxy_type_str(curproxy), curproxy->id,
7973 newsrv->id, other_srv->conf.line);
7974 break;
7975 }
7976 }
7977 }
7978
Willy Tarreaudd701652010-05-25 23:03:02 +02007979 /* assign automatic UIDs to servers which don't have one yet */
7980 next_id = 1;
7981 newsrv = curproxy->srv;
7982 while (newsrv != NULL) {
7983 if (!newsrv->puid) {
7984 /* server ID not set, use automatic numbering with first
7985 * spare entry starting with next_svid.
7986 */
7987 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7988 newsrv->conf.id.key = newsrv->puid = next_id;
7989 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7990 }
7991 next_id++;
7992 newsrv = newsrv->next;
7993 }
7994
Willy Tarreau20697042007-11-15 23:26:18 +01007995 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007996 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007997
Willy Tarreau62c3be22012-01-20 13:12:32 +01007998 /*
7999 * If this server supports a maxconn parameter, it needs a dedicated
8000 * tasks to fill the emptied slots when a connection leaves.
8001 * Also, resolve deferred tracking dependency if needed.
8002 */
8003 newsrv = curproxy->srv;
8004 while (newsrv != NULL) {
8005 if (newsrv->minconn > newsrv->maxconn) {
8006 /* Only 'minconn' was specified, or it was higher than or equal
8007 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8008 * this will avoid further useless expensive computations.
8009 */
8010 newsrv->maxconn = newsrv->minconn;
8011 } else if (newsrv->maxconn && !newsrv->minconn) {
8012 /* minconn was not specified, so we set it to maxconn */
8013 newsrv->minconn = newsrv->maxconn;
8014 }
8015
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008016#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008017 if (newsrv->use_ssl || newsrv->check.use_ssl)
8018 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008019#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008020
Willy Tarreau2f075e92013-12-03 11:11:34 +01008021 /* set the check type on the server */
8022 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8023
Willy Tarreau62c3be22012-01-20 13:12:32 +01008024 if (newsrv->trackit) {
8025 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008026 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008027 char *pname, *sname;
8028
8029 pname = newsrv->trackit;
8030 sname = strrchr(pname, '/');
8031
8032 if (sname)
8033 *sname++ = '\0';
8034 else {
8035 sname = pname;
8036 pname = NULL;
8037 }
8038
8039 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008040 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008041 if (!px) {
8042 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8043 proxy_type_str(curproxy), curproxy->id,
8044 newsrv->id, pname);
8045 cfgerr++;
8046 goto next_srv;
8047 }
8048 } else
8049 px = curproxy;
8050
8051 srv = findserver(px, sname);
8052 if (!srv) {
8053 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8054 proxy_type_str(curproxy), curproxy->id,
8055 newsrv->id, sname);
8056 cfgerr++;
8057 goto next_srv;
8058 }
8059
Willy Tarreau32091232014-05-16 13:52:00 +02008060 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8061 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8062 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008063 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008064 "tracking as it does not have any check nor agent enabled.\n",
8065 proxy_type_str(curproxy), curproxy->id,
8066 newsrv->id, px->id, srv->id);
8067 cfgerr++;
8068 goto next_srv;
8069 }
8070
8071 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8072
8073 if (loop) {
8074 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8075 "belongs to a tracking chain looping back to %s/%s.\n",
8076 proxy_type_str(curproxy), curproxy->id,
8077 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008078 cfgerr++;
8079 goto next_srv;
8080 }
8081
8082 if (curproxy != px &&
8083 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8084 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8085 "tracking: disable-on-404 option inconsistency.\n",
8086 proxy_type_str(curproxy), curproxy->id,
8087 newsrv->id, px->id, srv->id);
8088 cfgerr++;
8089 goto next_srv;
8090 }
8091
8092 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008093 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008094 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008095 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008096 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008097 }
8098
8099 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008100 newsrv->tracknext = srv->trackers;
8101 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008102
8103 free(newsrv->trackit);
8104 newsrv->trackit = NULL;
8105 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008106
8107 /*
8108 * resolve server's resolvers name and update the resolvers pointer
8109 * accordingly
8110 */
8111 if (newsrv->resolvers_id) {
8112 struct dns_resolvers *curr_resolvers;
8113 int found;
8114
8115 found = 0;
8116 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8117 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8118 found = 1;
8119 break;
8120 }
8121 }
8122
8123 if (!found) {
8124 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8125 proxy_type_str(curproxy), curproxy->id,
8126 newsrv->id, newsrv->resolvers_id);
8127 cfgerr++;
8128 } else {
8129 free(newsrv->resolvers_id);
8130 newsrv->resolvers_id = NULL;
8131 if (newsrv->resolution)
8132 newsrv->resolution->resolvers = curr_resolvers;
8133 }
8134 }
8135 else {
8136 /* if no resolvers section associated to this server
8137 * we can clean up the associated resolution structure
8138 */
8139 if (newsrv->resolution) {
8140 free(newsrv->resolution->hostname_dn);
8141 newsrv->resolution->hostname_dn = NULL;
8142 free(newsrv->resolution);
8143 newsrv->resolution = NULL;
8144 }
8145 }
8146
Willy Tarreau62c3be22012-01-20 13:12:32 +01008147 next_srv:
8148 newsrv = newsrv->next;
8149 }
8150
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008151 /* We have to initialize the server lookup mechanism depending
8152 * on what LB algorithm was choosen.
8153 */
8154
8155 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8156 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8157 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008158 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8159 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8160 init_server_map(curproxy);
8161 } else {
8162 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8163 fwrr_init_server_groups(curproxy);
8164 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008165 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008166
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008167 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008168 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8169 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8170 fwlc_init_server_tree(curproxy);
8171 } else {
8172 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8173 fas_init_server_tree(curproxy);
8174 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008175 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008176
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008177 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008178 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8179 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8180 chash_init_server_tree(curproxy);
8181 } else {
8182 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8183 init_server_map(curproxy);
8184 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008185 break;
8186 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008187
8188 if (curproxy->options & PR_O_LOGASAP)
8189 curproxy->to_log &= ~LW_BYTES;
8190
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008191 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008192 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008193 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8194 proxy_type_str(curproxy), curproxy->id);
8195 err_code |= ERR_WARN;
8196 }
8197
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008198 if (curproxy->mode != PR_MODE_HTTP) {
8199 int optnum;
8200
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008201 if (curproxy->uri_auth) {
8202 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8203 proxy_type_str(curproxy), curproxy->id);
8204 err_code |= ERR_WARN;
8205 curproxy->uri_auth = NULL;
8206 }
8207
Willy Tarreau87cf5142011-08-19 22:57:24 +02008208 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008209 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8210 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8211 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008212 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008213 }
8214
8215 if (curproxy->options & PR_O_ORGTO) {
8216 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8217 "originalto", proxy_type_str(curproxy), curproxy->id);
8218 err_code |= ERR_WARN;
8219 curproxy->options &= ~PR_O_ORGTO;
8220 }
8221
8222 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8223 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8224 (curproxy->cap & cfg_opts[optnum].cap) &&
8225 (curproxy->options & cfg_opts[optnum].val)) {
8226 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8227 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8228 err_code |= ERR_WARN;
8229 curproxy->options &= ~cfg_opts[optnum].val;
8230 }
8231 }
8232
8233 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8234 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8235 (curproxy->cap & cfg_opts2[optnum].cap) &&
8236 (curproxy->options2 & cfg_opts2[optnum].val)) {
8237 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8238 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8239 err_code |= ERR_WARN;
8240 curproxy->options2 &= ~cfg_opts2[optnum].val;
8241 }
8242 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008243
Pieter Baauwd551fb52013-05-08 22:49:23 +02008244#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008245 if (curproxy->conn_src.bind_hdr_occ) {
8246 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008247 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008248 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008249 err_code |= ERR_WARN;
8250 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008251#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008252 }
8253
Willy Tarreaubaaee002006-06-26 02:48:02 +02008254 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008255 * ensure that we're not cross-dressing a TCP server into HTTP.
8256 */
8257 newsrv = curproxy->srv;
8258 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008259 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008260 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8261 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008262 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008263 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008264
Willy Tarreau0cec3312011-10-31 13:49:26 +01008265 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8266 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8267 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8268 err_code |= ERR_WARN;
8269 }
8270
Willy Tarreauc93cd162014-05-13 15:54:22 +02008271 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008272 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8273 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8274 err_code |= ERR_WARN;
8275 }
8276
Pieter Baauwd551fb52013-05-08 22:49:23 +02008277#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008278 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8279 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008280 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 +01008281 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008282 err_code |= ERR_WARN;
8283 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008284#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008285 newsrv = newsrv->next;
8286 }
8287
Willy Tarreaue42bd962014-09-16 16:21:19 +02008288 /* check if we have a frontend with "tcp-request content" looking at L7
8289 * with no inspect-delay
8290 */
8291 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8292 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
8293 if (trule->action == TCP_ACT_CAPTURE &&
8294 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8295 break;
8296 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
8297 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8298 break;
8299 }
8300
8301 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8302 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8303 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8304 " This means that these rules will randomly find their contents. This can be fixed by"
8305 " setting the tcp-request inspect-delay.\n",
8306 proxy_type_str(curproxy), curproxy->id);
8307 err_code |= ERR_WARN;
8308 }
8309 }
8310
Willy Tarreauc1a21672009-08-16 22:37:44 +02008311 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008312 if (!curproxy->accept)
8313 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008314
Willy Tarreauc1a21672009-08-16 22:37:44 +02008315 if (curproxy->tcp_req.inspect_delay ||
8316 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008317 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008318
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008319 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008320 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008321 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008322 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008323
8324 /* both TCP and HTTP must check switching rules */
8325 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8326 }
8327
8328 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008329 if (curproxy->tcp_req.inspect_delay ||
8330 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8331 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8332
Emeric Brun97679e72010-09-23 17:56:44 +02008333 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8334 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8335
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008336 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008337 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008338 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008339 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008340
8341 /* If the backend does requires RDP cookie persistence, we have to
8342 * enable the corresponding analyser.
8343 */
8344 if (curproxy->options2 & PR_O2_RDPC_PRST)
8345 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8346 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008347 }
8348
8349 /***********************************************************/
8350 /* At this point, target names have already been resolved. */
8351 /***********************************************************/
8352
8353 /* Check multi-process mode compatibility */
8354
8355 if (global.nbproc > 1 && global.stats_fe) {
8356 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8357 unsigned long mask;
8358
8359 mask = nbits(global.nbproc);
8360 if (global.stats_fe->bind_proc)
8361 mask &= global.stats_fe->bind_proc;
8362
8363 if (bind_conf->bind_proc)
8364 mask &= bind_conf->bind_proc;
8365
8366 /* stop here if more than one process is used */
8367 if (popcount(mask) > 1)
8368 break;
8369 }
8370 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8371 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");
8372 }
8373 }
8374
8375 /* Make each frontend inherit bind-process from its listeners when not specified. */
8376 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8377 if (curproxy->bind_proc)
8378 continue;
8379
8380 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8381 unsigned long mask;
8382
Willy Tarreaue428b082015-05-04 21:57:58 +02008383 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008384 curproxy->bind_proc |= mask;
8385 }
8386
8387 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008388 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008389 }
8390
8391 if (global.stats_fe) {
8392 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8393 unsigned long mask;
8394
Willy Tarreaue428b082015-05-04 21:57:58 +02008395 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008396 global.stats_fe->bind_proc |= mask;
8397 }
8398 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008399 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008400 }
8401
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008402 /* propagate bindings from frontends to backends. Don't do it if there
8403 * are any fatal errors as we must not call it with unresolved proxies.
8404 */
8405 if (!cfgerr) {
8406 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8407 if (curproxy->cap & PR_CAP_FE)
8408 propagate_processes(curproxy, NULL);
8409 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008410 }
8411
8412 /* Bind each unbound backend to all processes when not specified. */
8413 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8414 if (curproxy->bind_proc)
8415 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008416 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008417 }
8418
8419 /*******************************************************/
8420 /* At this step, all proxies have a non-null bind_proc */
8421 /*******************************************************/
8422
8423 /* perform the final checks before creating tasks */
8424
8425 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8426 struct listener *listener;
8427 unsigned int next_id;
8428 int nbproc;
8429
8430 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008431
Emeric Brunc52962f2012-11-15 18:28:02 +01008432#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008433 /* Configure SSL for each bind line.
8434 * Note: if configuration fails at some point, the ->ctx member
8435 * remains NULL so that listeners can later detach.
8436 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008437 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008438 int alloc_ctx;
8439
Emeric Brunc52962f2012-11-15 18:28:02 +01008440 if (!bind_conf->is_ssl) {
8441 if (bind_conf->default_ctx) {
8442 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8443 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8444 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008445 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008446 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008447 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008448 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008449 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008450 cfgerr++;
8451 continue;
8452 }
8453
Emeric Brun8dc60392014-05-09 13:52:00 +02008454 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008455 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008456 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8457 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");
8458 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008459 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008460 cfgerr++;
8461 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008462 }
8463
Emeric Brunfc0421f2012-09-07 17:30:07 +02008464 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008465 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008466
8467 /* initialize CA variables if the certificates generation is enabled */
8468 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008469 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008470#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008471
Willy Tarreaue6b98942007-10-29 01:09:36 +01008472 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008473 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008474 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008475 if (!listener->luid) {
8476 /* listener ID not set, use automatic numbering with first
8477 * spare entry starting with next_luid.
8478 */
8479 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8480 listener->conf.id.key = listener->luid = next_id;
8481 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008482 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008483 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008484
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008485 /* enable separate counters */
8486 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8487 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008488 if (!listener->name)
8489 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008490 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008491
Willy Tarreaue6b98942007-10-29 01:09:36 +01008492 if (curproxy->options & PR_O_TCP_NOLING)
8493 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008494 if (!listener->maxconn)
8495 listener->maxconn = curproxy->maxconn;
8496 if (!listener->backlog)
8497 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008498 if (!listener->maxaccept)
8499 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8500
8501 /* we want to have an optimal behaviour on single process mode to
8502 * maximize the work at once, but in multi-process we want to keep
8503 * some fairness between processes, so we target half of the max
8504 * number of events to be balanced over all the processes the proxy
8505 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8506 * used to disable the limit.
8507 */
8508 if (listener->maxaccept > 0) {
8509 if (nbproc > 1)
8510 listener->maxaccept = (listener->maxaccept + 1) / 2;
8511 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8512 }
8513
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008514 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008515 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008516 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008517 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008518
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008519 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8520 listener->options |= LI_O_TCP_RULES;
8521
Willy Tarreaude3041d2010-05-31 10:56:17 +02008522 if (curproxy->mon_mask.s_addr)
8523 listener->options |= LI_O_CHK_MONNET;
8524
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008525 /* smart accept mode is automatic in HTTP mode */
8526 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008527 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008528 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8529 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008530 }
8531
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008532 /* Release unused SSL configs */
8533 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8534 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008535 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008536#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008537 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008538 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008539 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008540 free(bind_conf->ca_sign_file);
8541 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008542 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008543 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008544 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008545 if(bind_conf->keys_ref) {
8546 free(bind_conf->keys_ref->filename);
8547 free(bind_conf->keys_ref->tlskeys);
8548 free(bind_conf->keys_ref);
8549 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008550#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008551 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008552
Willy Tarreau102df612014-05-07 23:56:38 +02008553 if (nbproc > 1) {
8554 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008555 int count, maxproc = 0;
8556
8557 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8558 count = popcount(bind_conf->bind_proc);
8559 if (count > maxproc)
8560 maxproc = count;
8561 }
8562 /* backends have 0, frontends have 1 or more */
8563 if (maxproc != 1)
8564 Warning("Proxy '%s': in multi-process mode, stats will be"
8565 " limited to process assigned to the current request.\n",
8566 curproxy->id);
8567
Willy Tarreau102df612014-05-07 23:56:38 +02008568 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8569 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8570 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008571 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008572 }
Willy Tarreau102df612014-05-07 23:56:38 +02008573 if (curproxy->appsession_name) {
8574 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8575 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008576 }
Willy Tarreau102df612014-05-07 23:56:38 +02008577 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8578 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8579 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008580 }
8581 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008582
8583 /* create the task associated with the proxy */
8584 curproxy->task = task_new();
8585 if (curproxy->task) {
8586 curproxy->task->context = curproxy;
8587 curproxy->task->process = manage_proxy;
8588 /* no need to queue, it will be done automatically if some
8589 * listener gets limited.
8590 */
8591 curproxy->task->expire = TICK_ETERNITY;
8592 } else {
8593 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8594 curproxy->id);
8595 cfgerr++;
8596 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008597 }
8598
Willy Tarreaufbb78422011-06-05 15:38:35 +02008599 /* automatically compute fullconn if not set. We must not do it in the
8600 * loop above because cross-references are not yet fully resolved.
8601 */
8602 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8603 /* If <fullconn> is not set, let's set it to 10% of the sum of
8604 * the possible incoming frontend's maxconns.
8605 */
8606 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8607 struct proxy *fe;
8608 int total = 0;
8609
8610 /* sum up the number of maxconns of frontends which
8611 * reference this backend at least once or which are
8612 * the same one ('listen').
8613 */
8614 for (fe = proxy; fe; fe = fe->next) {
8615 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008616 int found = 0;
8617
8618 if (!(fe->cap & PR_CAP_FE))
8619 continue;
8620
8621 if (fe == curproxy) /* we're on a "listen" instance */
8622 found = 1;
8623
8624 if (fe->defbe.be == curproxy) /* "default_backend" */
8625 found = 1;
8626
8627 /* check if a "use_backend" rule matches */
8628 if (!found) {
8629 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008630 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008631 found = 1;
8632 break;
8633 }
8634 }
8635 }
8636
Willy Tarreaufbb78422011-06-05 15:38:35 +02008637 /* now we've checked all possible ways to reference a backend
8638 * from a frontend.
8639 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008640 if (!found)
8641 continue;
8642 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008643 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008644 /* we have the sum of the maxconns in <total>. We only
8645 * keep 10% of that sum to set the default fullconn, with
8646 * a hard minimum of 1 (to avoid a divide by zero).
8647 */
8648 curproxy->fullconn = (total + 9) / 10;
8649 if (!curproxy->fullconn)
8650 curproxy->fullconn = 1;
8651 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008652 }
8653
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008654 /*
8655 * Recount currently required checks.
8656 */
8657
8658 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8659 int optnum;
8660
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008661 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8662 if (curproxy->options & cfg_opts[optnum].val)
8663 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008664
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008665 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8666 if (curproxy->options2 & cfg_opts2[optnum].val)
8667 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008668 }
8669
Willy Tarreau0fca4832015-05-01 19:12:05 +02008670 /* compute the required process bindings for the peers */
8671 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8672 if (curproxy->table.peers.p)
8673 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8674
Willy Tarreau122541c2011-09-07 21:24:49 +02008675 if (peers) {
8676 struct peers *curpeers = peers, **last;
8677 struct peer *p, *pb;
8678
Willy Tarreau1e273012015-05-01 19:15:17 +02008679 /* Remove all peers sections which don't have a valid listener,
8680 * which are not used by any table, or which are bound to more
8681 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008682 */
8683 last = &peers;
8684 while (*last) {
8685 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008686
8687 if (curpeers->state == PR_STSTOPPED) {
8688 /* the "disabled" keyword was present */
8689 if (curpeers->peers_fe)
8690 stop_proxy(curpeers->peers_fe);
8691 curpeers->peers_fe = NULL;
8692 }
8693 else if (!curpeers->peers_fe) {
8694 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8695 curpeers->id, localpeer);
8696 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008697 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8698 /* either it's totally stopped or too much used */
8699 if (curpeers->peers_fe->bind_proc) {
8700 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008701 "running in different processes (%d different ones). "
8702 "Check global.nbproc and all tables' bind-process "
8703 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008704 cfgerr++;
8705 }
8706 stop_proxy(curpeers->peers_fe);
8707 curpeers->peers_fe = NULL;
8708 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008709 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008710 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008711 last = &curpeers->next;
8712 continue;
8713 }
8714
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008715 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008716 p = curpeers->remote;
8717 while (p) {
8718 pb = p->next;
8719 free(p->id);
8720 free(p);
8721 p = pb;
8722 }
8723
8724 /* Destroy and unlink this curpeers section.
8725 * Note: curpeers is backed up into *last.
8726 */
8727 free(curpeers->id);
8728 curpeers = curpeers->next;
8729 free(*last);
8730 *last = curpeers;
8731 }
8732 }
8733
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008734 /* initialize stick-tables on backend capable proxies. This must not
8735 * be done earlier because the data size may be discovered while parsing
8736 * other proxies.
8737 */
8738 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8739 if (curproxy->state == PR_STSTOPPED)
8740 continue;
8741
8742 if (!stktable_init(&curproxy->table)) {
8743 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8744 cfgerr++;
8745 }
8746 }
8747
Simon Horman0d16a402015-01-30 11:22:58 +09008748 if (mailers) {
8749 struct mailers *curmailers = mailers, **last;
8750 struct mailer *m, *mb;
8751
8752 /* Remove all mailers sections which don't have a valid listener.
8753 * This can happen when a mailers section is never referenced.
8754 */
8755 last = &mailers;
8756 while (*last) {
8757 curmailers = *last;
8758 if (curmailers->users) {
8759 last = &curmailers->next;
8760 continue;
8761 }
8762
8763 Warning("Removing incomplete section 'mailers %s'.\n",
8764 curmailers->id);
8765
8766 m = curmailers->mailer_list;
8767 while (m) {
8768 mb = m->next;
8769 free(m->id);
8770 free(m);
8771 m = mb;
8772 }
8773
8774 /* Destroy and unlink this curmailers section.
8775 * Note: curmailers is backed up into *last.
8776 */
8777 free(curmailers->id);
8778 curmailers = curmailers->next;
8779 free(*last);
8780 *last = curmailers;
8781 }
8782 }
8783
Willy Tarreau34eb6712011-10-24 18:15:04 +02008784 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008785 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008786 MEM_F_SHARED);
8787
Willy Tarreaubb925012009-07-23 13:36:36 +02008788 if (cfgerr > 0)
8789 err_code |= ERR_ALERT | ERR_FATAL;
8790 out:
8791 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008792}
8793
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008794/*
8795 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8796 * parsing sessions.
8797 */
8798void cfg_register_keywords(struct cfg_kw_list *kwl)
8799{
8800 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8801}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008802
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008803/*
8804 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8805 */
8806void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8807{
8808 LIST_DEL(&kwl->list);
8809 LIST_INIT(&kwl->list);
8810}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008811
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008812/* this function register new section in the haproxy configuration file.
8813 * <section_name> is the name of this new section and <section_parser>
8814 * is the called parser. If two section declaration have the same name,
8815 * only the first declared is used.
8816 */
8817int cfg_register_section(char *section_name,
8818 int (*section_parser)(const char *, int, char **, int))
8819{
8820 struct cfg_section *cs;
8821
8822 cs = calloc(1, sizeof(*cs));
8823 if (!cs) {
8824 Alert("register section '%s': out of memory.\n", section_name);
8825 return 0;
8826 }
8827
8828 cs->section_name = section_name;
8829 cs->section_parser = section_parser;
8830
8831 LIST_ADDQ(&sections, &cs->list);
8832
8833 return 1;
8834}
8835
Willy Tarreaubaaee002006-06-26 02:48:02 +02008836/*
8837 * Local variables:
8838 * c-indent-level: 8
8839 * c-basic-offset: 8
8840 * End:
8841 */