blob: 08adccdc124658bf6217611ea3e1005bba7fa10c [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020052#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020053
Willy Tarreaueb0c6142007-05-07 00:53:22 +020054#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010055#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020056#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020057#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020058#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020059#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020060#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020061#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020062#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020063#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010064#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020065#include <proto/lb_fwlc.h>
66#include <proto/lb_fwrr.h>
67#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020068#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020069#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010071#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020072#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010074#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020075#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020076#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020077#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020078#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020079#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020080#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020081#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010082#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083
Emeric Brunfc0421f2012-09-07 17:30:07 +020084#ifdef USE_OPENSSL
85#include <types/ssl_sock.h>
86#include <proto/ssl_sock.h>
87#include <proto/shctx.h>
88#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020089
Willy Tarreauf3c69202006-07-09 16:42:34 +020090/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
91 * ssl-hello-chk option to ensure that the remote server speaks SSL.
92 *
93 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
94 */
95const char sslv3_client_hello_pkt[] = {
96 "\x16" /* ContentType : 0x16 = Hanshake */
97 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
98 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
99 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
100 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
101 "\x03\x00" /* Hello Version : 0x0300 = v3 */
102 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
103 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
104 "\x00" /* Session ID length : empty (no session ID) */
105 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
106 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
107 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
108 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
109 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
110 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
111 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
112 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
113 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
114 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
115 "\x00\x38" "\x00\x39" "\x00\x3A"
116 "\x01" /* Compression Length : 0x01 = 1 byte for types */
117 "\x00" /* Compression Type : 0x00 = NULL compression */
118};
119
Willy Tarreau3842f002009-06-14 11:39:52 +0200120/* various keyword modifiers */
121enum kw_mod {
122 KWM_STD = 0, /* normal */
123 KWM_NO, /* "no" prefixed before the keyword */
124 KWM_DEF, /* "default" prefixed before the keyword */
125};
126
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100127/* permit to store configuration section */
128struct cfg_section {
129 struct list list;
130 char *section_name;
131 int (*section_parser)(const char *, int, char **, int);
132};
133
134/* Used to chain configuration sections definitions. This list
135 * stores struct cfg_section
136 */
137struct list sections = LIST_HEAD_INIT(sections);
138
Willy Tarreau13943ab2006-12-31 00:24:10 +0100139/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100140struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141 const char *name;
142 unsigned int val;
143 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100144 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100145 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100146};
147
148/* proxy->options */
149static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100150{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100151 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
152 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
153 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
154 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
155 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
156 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100157 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200158 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200159 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100160 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100161 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
162 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
163 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100164 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100165#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100167#else
168 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100169#endif
170
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100171 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100172};
173
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100174/* proxy->options2 */
175static const struct cfg_opt cfg_opts2[] =
176{
177#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100178 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
180 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100181#else
182 { "splice-request", 0, 0, 0, 0 },
183 { "splice-response", 0, 0, 0, 0 },
184 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100185#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100186 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
187 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
188 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
189 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
190 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
191 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
193 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
194 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400195 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100196 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200197 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200198 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100199 { NULL, 0, 0, 0 }
200};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200201
Willy Tarreau6daf3432008-01-22 16:44:08 +0100202static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
204int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100205int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200206
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200207/* List head of all known configuration keywords */
208static struct cfg_kw_list cfg_keywords = {
209 .list = LIST_HEAD_INIT(cfg_keywords.list)
210};
211
Willy Tarreaubaaee002006-06-26 02:48:02 +0200212/*
213 * converts <str> to a list of listeners which are dynamically allocated.
214 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
215 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
216 * - <port> is a numerical port from 1 to 65535 ;
217 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
218 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200219 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
220 * not NULL, it must be a valid pointer to either NULL or a freeable area that
221 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200222 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200223int str2listener(char *str, struct proxy *curproxy, struct bind_conf *bind_conf, const char *file, int line, char **err)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224{
225 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100226 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200227 int port, end;
228
229 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200230
Willy Tarreaubaaee002006-06-26 02:48:02 +0200231 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100232 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100233 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200234
235 str = next;
236 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100237 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 *next++ = 0;
239 }
240
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100241 ss2 = str2sa_range(str, &port, &end, err,
242 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
243 if (!ss2)
244 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100247 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200248 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100249 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200251
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100252 if (!port || !end) {
253 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
254 goto fail;
255 }
256
Emeric Bruned760922010-10-22 17:59:25 +0200257 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200258 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200259 goto fail;
260 }
261
262 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200263 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200264 goto fail;
265 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200266 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100267 else if (ss2->ss_family == AF_UNSPEC) {
268 socklen_t addr_len;
269
270 /* We want to attach to an already bound fd whose number
271 * is in the addr part of ss2 when cast to sockaddr_in.
272 * Note that by definition there is a single listener.
273 * We still have to determine the address family to
274 * register the correct protocol.
275 */
276 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
277 addr_len = sizeof(*ss2);
278 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
279 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
280 goto fail;
281 }
282
283 port = end = get_host_port(ss2);
284 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200285
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100286 /* OK the address looks correct */
287 ss = *ss2;
288
Willy Tarreaubaaee002006-06-26 02:48:02 +0200289 for (; port <= end; port++) {
290 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100291 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200292 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
293 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
294 l->frontend = curproxy;
295 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200296
Willy Tarreau40aa0702013-03-10 23:51:38 +0100297 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200298 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200299 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100300 l->state = LI_INIT;
301
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100302 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200303 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100304 tcpv4_add_listener(l);
305 }
Emeric Bruned760922010-10-22 17:59:25 +0200306 else if (ss.ss_family == AF_INET6) {
307 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
308 tcpv6_add_listener(l);
309 }
310 else {
Emeric Bruned760922010-10-22 17:59:25 +0200311 uxst_add_listener(l);
312 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200313
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200314 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100315 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200316 } /* end for(port) */
317 } /* end while(next) */
318 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200319 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200320 fail:
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323}
324
William Lallemand6e62fb62015-04-28 16:55:23 +0200325/*
326 * Report a fatal Alert when there is too much arguments
327 * The index is the current keyword in args
328 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
329 * Fill err_code with an ERR_ALERT and an ERR_FATAL
330 */
331int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
332{
333 char *kw = NULL;
334 int i;
335
336 if (!*args[index + maxarg + 1])
337 return 0;
338
339 memprintf(&kw, "%s", args[0]);
340 for (i = 1; i <= index; i++) {
341 memprintf(&kw, "%s %s", kw, args[i]);
342 }
343
344 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
345 free(kw);
346 *err_code |= ERR_ALERT | ERR_FATAL;
347 return 1;
348}
349
350/*
351 * same as alertif_too_many_args_idx with a 0 index
352 */
353int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
354{
355 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
356}
357
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200358/* Report a warning if a rule is placed after a 'tcp-request content' rule.
359 * Return 1 if the warning has been emitted, otherwise 0.
360 */
361int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
362{
363 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
364 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
365 file, line, arg);
366 return 1;
367 }
368 return 0;
369}
370
Willy Tarreau61d18892009-03-31 10:49:21 +0200371/* Report a warning if a rule is placed after a 'block' rule.
372 * Return 1 if the warning has been emitted, otherwise 0.
373 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100374int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200375{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200376 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200377 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
378 file, line, arg);
379 return 1;
380 }
381 return 0;
382}
383
Willy Tarreau5002f572014-04-23 01:32:02 +0200384/* Report a warning if a rule is placed after an 'http_request' rule.
385 * Return 1 if the warning has been emitted, otherwise 0.
386 */
387int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
388{
389 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
390 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
391 file, line, arg);
392 return 1;
393 }
394 return 0;
395}
396
Willy Tarreau61d18892009-03-31 10:49:21 +0200397/* Report a warning if a rule is placed after a reqrewrite rule.
398 * Return 1 if the warning has been emitted, otherwise 0.
399 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100400int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200401{
402 if (proxy->req_exp) {
403 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
404 file, line, arg);
405 return 1;
406 }
407 return 0;
408}
409
410/* Report a warning if a rule is placed after a reqadd rule.
411 * Return 1 if the warning has been emitted, otherwise 0.
412 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100413int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200414{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100415 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200416 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
417 file, line, arg);
418 return 1;
419 }
420 return 0;
421}
422
423/* Report a warning if a rule is placed after a redirect rule.
424 * Return 1 if the warning has been emitted, otherwise 0.
425 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100426int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200427{
428 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
429 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
430 file, line, arg);
431 return 1;
432 }
433 return 0;
434}
435
436/* Report a warning if a rule is placed after a 'use_backend' rule.
437 * Return 1 if the warning has been emitted, otherwise 0.
438 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100439int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200440{
441 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
442 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
443 file, line, arg);
444 return 1;
445 }
446 return 0;
447}
448
Willy Tarreauee445d92014-04-23 01:39:04 +0200449/* Report a warning if a rule is placed after a 'use-server' rule.
450 * Return 1 if the warning has been emitted, otherwise 0.
451 */
452int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
453{
454 if (!LIST_ISEMPTY(&proxy->server_rules)) {
455 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
456 file, line, arg);
457 return 1;
458 }
459 return 0;
460}
461
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200462/* report a warning if a "tcp request connection" rule is dangerously placed */
463int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
464{
465 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
466 warnif_rule_after_block(proxy, file, line, arg) ||
467 warnif_rule_after_http_req(proxy, file, line, arg) ||
468 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
469 warnif_rule_after_reqadd(proxy, file, line, arg) ||
470 warnif_rule_after_redirect(proxy, file, line, arg) ||
471 warnif_rule_after_use_backend(proxy, file, line, arg) ||
472 warnif_rule_after_use_server(proxy, file, line, arg);
473}
474
475/* report a warning if a "tcp request content" rule is dangerously placed */
476int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
477{
478 return warnif_rule_after_block(proxy, file, line, arg) ||
479 warnif_rule_after_http_req(proxy, file, line, arg) ||
480 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
481 warnif_rule_after_reqadd(proxy, file, line, arg) ||
482 warnif_rule_after_redirect(proxy, file, line, arg) ||
483 warnif_rule_after_use_backend(proxy, file, line, arg) ||
484 warnif_rule_after_use_server(proxy, file, line, arg);
485}
486
Willy Tarreau61d18892009-03-31 10:49:21 +0200487/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100488int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200489{
Willy Tarreau5002f572014-04-23 01:32:02 +0200490 return warnif_rule_after_http_req(proxy, file, line, arg) ||
491 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
492 warnif_rule_after_reqadd(proxy, file, line, arg) ||
493 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200494 warnif_rule_after_use_backend(proxy, file, line, arg) ||
495 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200496}
497
498/* report a warning if an http-request rule is dangerously placed */
499int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
500{
Willy Tarreau61d18892009-03-31 10:49:21 +0200501 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
502 warnif_rule_after_reqadd(proxy, file, line, arg) ||
503 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200504 warnif_rule_after_use_backend(proxy, file, line, arg) ||
505 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200506}
507
508/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100509int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200510{
511 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
512 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200513 warnif_rule_after_use_backend(proxy, file, line, arg) ||
514 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200515}
516
517/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100518int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200519{
520 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200521 warnif_rule_after_use_backend(proxy, file, line, arg) ||
522 warnif_rule_after_use_server(proxy, file, line, arg);
523}
524
525/* report a warning if a redirect rule is dangerously placed */
526int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
527{
528 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
529 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200530}
531
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100532/* Report it if a request ACL condition uses some keywords that are incompatible
533 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
534 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
535 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100536 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100537static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100538{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100539 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200540 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100543 return 0;
544
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100545 acl = acl_cond_conflicts(cond, where);
546 if (acl) {
547 if (acl->name && *acl->name)
548 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
549 file, line, acl->name, sample_ckp_names(where));
550 else
551 Warning("parsing [%s:%d] : anonymous acl will never match because it uses keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200552 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100553 return ERR_WARN;
554 }
555 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100556 return 0;
557
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100558 if (acl->name && *acl->name)
559 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200560 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 else
562 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200563 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100564 return ERR_WARN;
565}
566
Willy Tarreaubaaee002006-06-26 02:48:02 +0200567/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200568 * parse a line in a <global> section. Returns the error code, 0 if OK, or
569 * any combination of :
570 * - ERR_ABORT: must abort ASAP
571 * - ERR_FATAL: we can continue parsing but not start the service
572 * - ERR_WARN: a warning has been emitted
573 * - ERR_ALERT: an alert has been emitted
574 * Only the two first ones can stop processing, the two others are just
575 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200576 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200577int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200578{
Willy Tarreau058e9072009-07-20 09:30:05 +0200579 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200580 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581
582 if (!strcmp(args[0], "global")) { /* new section */
583 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200584 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200586 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200587 else if (!strcmp(args[0], "ca-base")) {
588#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200589 if(alertif_too_many_args(1, file, linenum, args, &err_code))
590 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200591 if (global.ca_base != NULL) {
592 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
593 err_code |= ERR_ALERT;
594 goto out;
595 }
596 if (*(args[1]) == 0) {
597 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
598 err_code |= ERR_ALERT | ERR_FATAL;
599 goto out;
600 }
601 global.ca_base = strdup(args[1]);
602#else
603 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
604 err_code |= ERR_ALERT | ERR_FATAL;
605 goto out;
606#endif
607 }
608 else if (!strcmp(args[0], "crt-base")) {
609#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200610 if (alertif_too_many_args(1, file, linenum, args, &err_code))
611 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200612 if (global.crt_base != NULL) {
613 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
614 err_code |= ERR_ALERT;
615 goto out;
616 }
617 if (*(args[1]) == 0) {
618 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
619 err_code |= ERR_ALERT | ERR_FATAL;
620 goto out;
621 }
622 global.crt_base = strdup(args[1]);
623#else
624 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
625 err_code |= ERR_ALERT | ERR_FATAL;
626 goto out;
627#endif
628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200629 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200630 if (alertif_too_many_args(0, file, linenum, args, &err_code))
631 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 global.mode |= MODE_DAEMON;
633 }
634 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200635 if (alertif_too_many_args(0, file, linenum, args, &err_code))
636 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200637 global.mode |= MODE_DEBUG;
638 }
639 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200640 if (alertif_too_many_args(0, file, linenum, args, &err_code))
641 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100642 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200643 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200644 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200645 if (alertif_too_many_args(0, file, linenum, args, &err_code))
646 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100647 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200648 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200649 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200650 if (alertif_too_many_args(0, file, linenum, args, &err_code))
651 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100652 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200653 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100654 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200655 if (alertif_too_many_args(0, file, linenum, args, &err_code))
656 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100657 global.tune.options &= ~GTUNE_USE_SPLICE;
658 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200659 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200660 if (alertif_too_many_args(0, file, linenum, args, &err_code))
661 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200662 global.tune.options &= ~GTUNE_USE_GAI;
663 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200664 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200665 if (alertif_too_many_args(0, file, linenum, args, &err_code))
666 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 global.mode |= MODE_QUIET;
668 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200669 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200670 if (alertif_too_many_args(1, file, linenum, args, &err_code))
671 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 if (global.tune.maxpollevents != 0) {
673 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200674 err_code |= ERR_ALERT;
675 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200676 }
677 if (*(args[1]) == 0) {
678 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200679 err_code |= ERR_ALERT | ERR_FATAL;
680 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200681 }
682 global.tune.maxpollevents = atol(args[1]);
683 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100684 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200685 if (alertif_too_many_args(1, file, linenum, args, &err_code))
686 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 if (global.tune.maxaccept != 0) {
688 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200689 err_code |= ERR_ALERT;
690 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100691 }
692 if (*(args[1]) == 0) {
693 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200694 err_code |= ERR_ALERT | ERR_FATAL;
695 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100696 }
697 global.tune.maxaccept = atol(args[1]);
698 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200699 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200700 if (alertif_too_many_args(1, file, linenum, args, &err_code))
701 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 if (*(args[1]) == 0) {
703 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
704 err_code |= ERR_ALERT | ERR_FATAL;
705 goto out;
706 }
707 global.tune.chksize = atol(args[1]);
708 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200709#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200710 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200711 if (alertif_too_many_args(0, file, linenum, args, &err_code))
712 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200713 global.tune.sslprivatecache = 1;
714 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100715 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200716 if (alertif_too_many_args(1, file, linenum, args, &err_code))
717 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200718 if (*(args[1]) == 0) {
719 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
720 err_code |= ERR_ALERT | ERR_FATAL;
721 goto out;
722 }
723 global.tune.sslcachesize = atol(args[1]);
724 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100725 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
726 unsigned int ssllifetime;
727 const char *res;
728
William Lallemand1a748ae2015-05-19 16:37:23 +0200729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
730 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100731 if (*(args[1]) == 0) {
732 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
733 err_code |= ERR_ALERT | ERR_FATAL;
734 goto out;
735 }
736
737 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
738 if (res) {
739 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
740 file, linenum, *res, args[0]);
741 err_code |= ERR_ALERT | ERR_FATAL;
742 goto out;
743 }
744
745 global.tune.ssllifetime = ssllifetime;
746 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100747 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200748 if (alertif_too_many_args(1, file, linenum, args, &err_code))
749 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100750 if (*(args[1]) == 0) {
751 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
752 err_code |= ERR_ALERT | ERR_FATAL;
753 goto out;
754 }
755 global.tune.ssl_max_record = atol(args[1]);
756 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200757#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200758 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200759 if (alertif_too_many_args(1, file, linenum, args, &err_code))
760 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200761 if (*(args[1]) == 0) {
762 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
763 err_code |= ERR_ALERT | ERR_FATAL;
764 goto out;
765 }
766 global.tune.ssl_default_dh_param = atol(args[1]);
767 if (global.tune.ssl_default_dh_param < 1024) {
768 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
769 err_code |= ERR_ALERT | ERR_FATAL;
770 goto out;
771 }
772 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200773#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200774 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
775 if (alertif_too_many_args(1, file, linenum, args, &err_code))
776 goto out;
777 if (*(args[1]) == 0) {
778 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
779 err_code |= ERR_ALERT | ERR_FATAL;
780 goto out;
781 }
782 global.tune.ssl_ctx_cache = atoi(args[1]);
783 if (global.tune.ssl_ctx_cache < 0) {
784 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
785 file, linenum, args[0]);
786 err_code |= ERR_ALERT | ERR_FATAL;
787 goto out;
788 }
789 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200790#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100791 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200792 if (alertif_too_many_args(1, file, linenum, args, &err_code))
793 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.buf_limit = atol(args[1]);
800 if (global.tune.buf_limit) {
801 if (global.tune.buf_limit < 3)
802 global.tune.buf_limit = 3;
803 if (global.tune.buf_limit <= global.tune.reserved_bufs)
804 global.tune.buf_limit = global.tune.reserved_bufs + 1;
805 }
806 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100807 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200808 if (alertif_too_many_args(1, file, linenum, args, &err_code))
809 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100810 if (*(args[1]) == 0) {
811 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
812 err_code |= ERR_ALERT | ERR_FATAL;
813 goto out;
814 }
815 global.tune.reserved_bufs = atol(args[1]);
816 if (global.tune.reserved_bufs < 2)
817 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100818 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
819 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100820 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200821 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200822 if (alertif_too_many_args(1, file, linenum, args, &err_code))
823 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200824 if (*(args[1]) == 0) {
825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
826 err_code |= ERR_ALERT | ERR_FATAL;
827 goto out;
828 }
829 global.tune.bufsize = atol(args[1]);
830 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
831 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100832 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100833 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200834 }
835 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200838 if (*(args[1]) == 0) {
839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 global.tune.maxrewrite = atol(args[1]);
844 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
845 global.tune.maxrewrite = global.tune.bufsize / 2;
846 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100847 else if (!strcmp(args[0], "tune.idletimer")) {
848 unsigned int idle;
849 const char *res;
850
William Lallemand1a748ae2015-05-19 16:37:23 +0200851 if (alertif_too_many_args(1, file, linenum, args, &err_code))
852 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100853 if (*(args[1]) == 0) {
854 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
855 err_code |= ERR_ALERT | ERR_FATAL;
856 goto out;
857 }
858
859 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
860 if (res) {
861 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
862 file, linenum, *res, args[0]);
863 err_code |= ERR_ALERT | ERR_FATAL;
864 goto out;
865 }
866
867 if (idle > 65535) {
868 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
869 err_code |= ERR_ALERT | ERR_FATAL;
870 goto out;
871 }
872 global.tune.idle_timer = idle;
873 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100874 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200875 if (alertif_too_many_args(1, file, linenum, args, &err_code))
876 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100877 if (global.tune.client_rcvbuf != 0) {
878 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
879 err_code |= ERR_ALERT;
880 goto out;
881 }
882 if (*(args[1]) == 0) {
883 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
884 err_code |= ERR_ALERT | ERR_FATAL;
885 goto out;
886 }
887 global.tune.client_rcvbuf = atol(args[1]);
888 }
889 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200890 if (alertif_too_many_args(1, file, linenum, args, &err_code))
891 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100892 if (global.tune.server_rcvbuf != 0) {
893 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
894 err_code |= ERR_ALERT;
895 goto out;
896 }
897 if (*(args[1]) == 0) {
898 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
899 err_code |= ERR_ALERT | ERR_FATAL;
900 goto out;
901 }
902 global.tune.server_rcvbuf = atol(args[1]);
903 }
904 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200905 if (alertif_too_many_args(1, file, linenum, args, &err_code))
906 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100907 if (global.tune.client_sndbuf != 0) {
908 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
909 err_code |= ERR_ALERT;
910 goto out;
911 }
912 if (*(args[1]) == 0) {
913 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
914 err_code |= ERR_ALERT | ERR_FATAL;
915 goto out;
916 }
917 global.tune.client_sndbuf = atol(args[1]);
918 }
919 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200920 if (alertif_too_many_args(1, file, linenum, args, &err_code))
921 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100922 if (global.tune.server_sndbuf != 0) {
923 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
924 err_code |= ERR_ALERT;
925 goto out;
926 }
927 if (*(args[1]) == 0) {
928 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
929 err_code |= ERR_ALERT | ERR_FATAL;
930 goto out;
931 }
932 global.tune.server_sndbuf = atol(args[1]);
933 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200934 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200935 if (alertif_too_many_args(1, file, linenum, args, &err_code))
936 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200937 if (*(args[1]) == 0) {
938 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
939 err_code |= ERR_ALERT | ERR_FATAL;
940 goto out;
941 }
942 global.tune.pipesize = atol(args[1]);
943 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100944 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200945 if (alertif_too_many_args(1, file, linenum, args, &err_code))
946 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 global.tune.cookie_len = atol(args[1]) + 1;
953 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200954 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200955 if (alertif_too_many_args(1, file, linenum, args, &err_code))
956 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200957 if (*(args[1]) == 0) {
958 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
959 err_code |= ERR_ALERT | ERR_FATAL;
960 goto out;
961 }
962 global.tune.max_http_hdr = atol(args[1]);
963 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100964 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
965#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200966 if (alertif_too_many_args(1, file, linenum, args, &err_code))
967 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100968 if (*args[1]) {
969 global.tune.zlibmemlevel = atoi(args[1]);
970 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
971 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
972 file, linenum, args[0]);
973 err_code |= ERR_ALERT | ERR_FATAL;
974 goto out;
975 }
976 } else {
977 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
978 file, linenum, args[0]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981 }
982#else
983 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
984 err_code |= ERR_ALERT | ERR_FATAL;
985 goto out;
986#endif
987 }
988 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
989#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200990 if (alertif_too_many_args(1, file, linenum, args, &err_code))
991 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100992 if (*args[1]) {
993 global.tune.zlibwindowsize = atoi(args[1]);
994 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
995 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
996 file, linenum, args[0]);
997 err_code |= ERR_ALERT | ERR_FATAL;
998 goto out;
999 }
1000 } else {
1001 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1002 file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005 }
1006#else
1007 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1008 err_code |= ERR_ALERT | ERR_FATAL;
1009 goto out;
1010#endif
1011 }
William Lallemandf3747832012-11-09 12:33:10 +01001012 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001013 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1014 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001015 if (*args[1]) {
1016 global.tune.comp_maxlevel = atoi(args[1]);
1017 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1018 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1019 file, linenum, args[0]);
1020 err_code |= ERR_ALERT | ERR_FATAL;
1021 goto out;
1022 }
1023 } else {
1024 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1025 file, linenum, args[0]);
1026 err_code |= ERR_ALERT | ERR_FATAL;
1027 goto out;
1028 }
1029 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001030 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1031 if (*args[1]) {
1032 global.tune.pattern_cache = atoi(args[1]);
1033 if (global.tune.pattern_cache < 0) {
1034 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1035 file, linenum, args[0]);
1036 err_code |= ERR_ALERT | ERR_FATAL;
1037 goto out;
1038 }
1039 } else {
1040 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1041 file, linenum, args[0]);
1042 err_code |= ERR_ALERT | ERR_FATAL;
1043 goto out;
1044 }
1045 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001046 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001047 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001049 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001050 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001051 err_code |= ERR_ALERT;
1052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001053 }
1054 if (*(args[1]) == 0) {
1055 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001056 err_code |= ERR_ALERT | ERR_FATAL;
1057 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001058 }
1059 global.uid = atol(args[1]);
1060 }
1061 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001062 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1063 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001064 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001065 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001066 err_code |= ERR_ALERT;
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 }
1069 if (*(args[1]) == 0) {
1070 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001071 err_code |= ERR_ALERT | ERR_FATAL;
1072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001073 }
1074 global.gid = atol(args[1]);
1075 }
Simon Horman98637e52014-06-20 12:30:16 +09001076 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001077 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1078 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001079 global.external_check = 1;
1080 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001081 /* user/group name handling */
1082 else if (!strcmp(args[0], "user")) {
1083 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001084 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1085 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001086 if (global.uid != 0) {
1087 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001088 err_code |= ERR_ALERT;
1089 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001090 }
1091 errno = 0;
1092 ha_user = getpwnam(args[1]);
1093 if (ha_user != NULL) {
1094 global.uid = (int)ha_user->pw_uid;
1095 }
1096 else {
1097 Alert("parsing [%s:%d] : cannot find user id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001098 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001099 }
1100 }
1101 else if (!strcmp(args[0], "group")) {
1102 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001105 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001106 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT;
1108 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 }
1110 errno = 0;
1111 ha_group = getgrnam(args[1]);
1112 if (ha_group != NULL) {
1113 global.gid = (int)ha_group->gr_gid;
1114 }
1115 else {
1116 Alert("parsing [%s:%d] : cannot find group id for '%s' (%d:%s)\n", file, linenum, args[1], errno, strerror(errno));
Willy Tarreau058e9072009-07-20 09:30:05 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 }
1120 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001121 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001122 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
1129 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001130 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1131 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1132 file, linenum, args[0], LONGBITS, global.nbproc);
1133 err_code |= ERR_ALERT | ERR_FATAL;
1134 goto out;
1135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001136 }
1137 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001138 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1139 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 if (global.maxconn != 0) {
1141 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001142 err_code |= ERR_ALERT;
1143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001144 }
1145 if (*(args[1]) == 0) {
1146 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT | ERR_FATAL;
1148 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 }
1150 global.maxconn = atol(args[1]);
1151#ifdef SYSTEM_MAXCONN
1152 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1153 Alert("parsing [%s:%d] : maxconn value %d too high for this system.\nLimiting to %d. Please use '-n' to force the value.\n", file, linenum, global.maxconn, DEFAULT_MAXCONN);
1154 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001155 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157#endif /* SYSTEM_MAXCONN */
1158 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001159 else if (!strcmp(args[0], "maxsslconn")) {
1160#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001161 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1162 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001163 if (*(args[1]) == 0) {
1164 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1165 err_code |= ERR_ALERT | ERR_FATAL;
1166 goto out;
1167 }
1168 global.maxsslconn = atol(args[1]);
1169#else
Emeric Brun0914df82012-10-02 18:45:42 +02001170 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1171 err_code |= ERR_ALERT | ERR_FATAL;
1172 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001173#endif
1174 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001175 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1176#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001177 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1178 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001179 if (*(args[1]) == 0) {
1180 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1181 err_code |= ERR_ALERT | ERR_FATAL;
1182 goto out;
1183 }
1184 free(global.listen_default_ciphers);
1185 global.listen_default_ciphers = strdup(args[1]);
1186#else
1187 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1188 err_code |= ERR_ALERT | ERR_FATAL;
1189 goto out;
1190#endif
1191 }
1192 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1193#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001194 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1195 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001196 if (*(args[1]) == 0) {
1197 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1198 err_code |= ERR_ALERT | ERR_FATAL;
1199 goto out;
1200 }
1201 free(global.connect_default_ciphers);
1202 global.connect_default_ciphers = strdup(args[1]);
1203#else
1204 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1205 err_code |= ERR_ALERT | ERR_FATAL;
1206 goto out;
1207#endif
1208 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001209#ifdef USE_OPENSSL
1210#ifndef OPENSSL_NO_DH
1211 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1212 if (*(args[1]) == 0) {
1213 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1214 err_code |= ERR_ALERT | ERR_FATAL;
1215 goto out;
1216 }
1217 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1218 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1219 err_code |= ERR_ALERT | ERR_FATAL;
1220 goto out;
1221 }
1222 }
1223#endif
1224#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001225 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001226 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1227 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001228 if (*(args[1]) == 0) {
1229 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
1232 }
1233 if (strcmp(args[1],"none") == 0)
1234 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1235 else if (strcmp(args[1],"required") == 0)
1236 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1237 else {
1238 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1239 err_code |= ERR_ALERT | ERR_FATAL;
1240 goto out;
1241 }
1242 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001243 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001244 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1245 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001246 if (global.cps_lim != 0) {
1247 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1248 err_code |= ERR_ALERT;
1249 goto out;
1250 }
1251 if (*(args[1]) == 0) {
1252 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1253 err_code |= ERR_ALERT | ERR_FATAL;
1254 goto out;
1255 }
1256 global.cps_lim = atol(args[1]);
1257 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001258 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001259 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1260 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001261 if (global.sps_lim != 0) {
1262 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1263 err_code |= ERR_ALERT;
1264 goto out;
1265 }
1266 if (*(args[1]) == 0) {
1267 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1268 err_code |= ERR_ALERT | ERR_FATAL;
1269 goto out;
1270 }
1271 global.sps_lim = atol(args[1]);
1272 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001273 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001274 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1275 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001276 if (global.ssl_lim != 0) {
1277 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1278 err_code |= ERR_ALERT;
1279 goto out;
1280 }
1281 if (*(args[1]) == 0) {
1282 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1283 err_code |= ERR_ALERT | ERR_FATAL;
1284 goto out;
1285 }
1286 global.ssl_lim = atol(args[1]);
1287 }
William Lallemandd85f9172012-11-09 17:05:39 +01001288 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001289 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1290 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001291 if (*(args[1]) == 0) {
1292 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1293 err_code |= ERR_ALERT | ERR_FATAL;
1294 goto out;
1295 }
1296 global.comp_rate_lim = atoi(args[1]) * 1024;
1297 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001298 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001299 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1300 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001301 if (global.maxpipes != 0) {
1302 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001303 err_code |= ERR_ALERT;
1304 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001305 }
1306 if (*(args[1]) == 0) {
1307 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001308 err_code |= ERR_ALERT | ERR_FATAL;
1309 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001310 }
1311 global.maxpipes = atol(args[1]);
1312 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001313 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001314 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1315 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001316 if (*(args[1]) == 0) {
1317 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1318 err_code |= ERR_ALERT | ERR_FATAL;
1319 goto out;
1320 }
William Lallemande3a7d992012-11-20 11:25:20 +01001321 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001322 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001323 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001324 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1325 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001326 if (*(args[1]) == 0) {
1327 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1328 err_code |= ERR_ALERT | ERR_FATAL;
1329 goto out;
1330 }
1331 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001332 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001333 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1334 err_code |= ERR_ALERT | ERR_FATAL;
1335 goto out;
1336 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001337 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001338
Willy Tarreaubaaee002006-06-26 02:48:02 +02001339 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001340 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1341 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001342 if (global.rlimit_nofile != 0) {
1343 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001344 err_code |= ERR_ALERT;
1345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001346 }
1347 if (*(args[1]) == 0) {
1348 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001349 err_code |= ERR_ALERT | ERR_FATAL;
1350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001351 }
1352 global.rlimit_nofile = atol(args[1]);
1353 }
1354 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001355 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1356 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001357 if (global.chroot != NULL) {
1358 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001359 err_code |= ERR_ALERT;
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 }
1362 if (*(args[1]) == 0) {
1363 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001364 err_code |= ERR_ALERT | ERR_FATAL;
1365 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001366 }
1367 global.chroot = strdup(args[1]);
1368 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001369 else if (!strcmp(args[0], "description")) {
1370 int i, len=0;
1371 char *d;
1372
1373 if (!*args[1]) {
1374 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1375 file, linenum, args[0]);
1376 err_code |= ERR_ALERT | ERR_FATAL;
1377 goto out;
1378 }
1379
Willy Tarreau348acfe2014-04-14 15:00:39 +02001380 for (i = 1; *args[i]; i++)
1381 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001382
1383 if (global.desc)
1384 free(global.desc);
1385
1386 global.desc = d = (char *)calloc(1, len);
1387
Willy Tarreau348acfe2014-04-14 15:00:39 +02001388 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1389 for (i = 2; *args[i]; i++)
1390 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001391 }
1392 else if (!strcmp(args[0], "node")) {
1393 int i;
1394 char c;
1395
William Lallemand1a748ae2015-05-19 16:37:23 +02001396 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1397 goto out;
1398
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001399 for (i=0; args[1][i]; i++) {
1400 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001401 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1402 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001403 break;
1404 }
1405
1406 if (!i || args[1][i]) {
1407 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1408 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1409 file, linenum, args[0]);
1410 err_code |= ERR_ALERT | ERR_FATAL;
1411 goto out;
1412 }
1413
1414 if (global.node)
1415 free(global.node);
1416
1417 global.node = strdup(args[1]);
1418 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001419 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001420 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1421 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001422 if (global.pidfile != NULL) {
1423 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001424 err_code |= ERR_ALERT;
1425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001426 }
1427 if (*(args[1]) == 0) {
1428 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001431 }
1432 global.pidfile = strdup(args[1]);
1433 }
Emeric Bruned760922010-10-22 17:59:25 +02001434 else if (!strcmp(args[0], "unix-bind")) {
1435 int cur_arg = 1;
1436 while (*(args[cur_arg])) {
1437 if (!strcmp(args[cur_arg], "prefix")) {
1438 if (global.unix_bind.prefix != NULL) {
1439 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1440 err_code |= ERR_ALERT;
1441 cur_arg += 2;
1442 continue;
1443 }
1444
1445 if (*(args[cur_arg+1]) == 0) {
1446 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1447 err_code |= ERR_ALERT | ERR_FATAL;
1448 goto out;
1449 }
1450 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1451 cur_arg += 2;
1452 continue;
1453 }
1454
1455 if (!strcmp(args[cur_arg], "mode")) {
1456
1457 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1458 cur_arg += 2;
1459 continue;
1460 }
1461
1462 if (!strcmp(args[cur_arg], "uid")) {
1463
1464 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1465 cur_arg += 2;
1466 continue;
1467 }
1468
1469 if (!strcmp(args[cur_arg], "gid")) {
1470
1471 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1472 cur_arg += 2;
1473 continue;
1474 }
1475
1476 if (!strcmp(args[cur_arg], "user")) {
1477 struct passwd *user;
1478
1479 user = getpwnam(args[cur_arg + 1]);
1480 if (!user) {
1481 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1482 file, linenum, args[0], args[cur_arg + 1 ]);
1483 err_code |= ERR_ALERT | ERR_FATAL;
1484 goto out;
1485 }
1486
1487 global.unix_bind.ux.uid = user->pw_uid;
1488 cur_arg += 2;
1489 continue;
1490 }
1491
1492 if (!strcmp(args[cur_arg], "group")) {
1493 struct group *group;
1494
1495 group = getgrnam(args[cur_arg + 1]);
1496 if (!group) {
1497 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1498 file, linenum, args[0], args[cur_arg + 1 ]);
1499 err_code |= ERR_ALERT | ERR_FATAL;
1500 goto out;
1501 }
1502
1503 global.unix_bind.ux.gid = group->gr_gid;
1504 cur_arg += 2;
1505 continue;
1506 }
1507
Willy Tarreaub48f9582011-09-05 01:17:06 +02001508 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001509 file, linenum, args[0]);
1510 err_code |= ERR_ALERT | ERR_FATAL;
1511 goto out;
1512 }
1513 }
William Lallemand0f99e342011-10-12 17:50:54 +02001514 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1515 /* delete previous herited or defined syslog servers */
1516 struct logsrv *back;
1517 struct logsrv *tmp;
1518
1519 if (*(args[1]) != 0) {
1520 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1521 err_code |= ERR_ALERT | ERR_FATAL;
1522 goto out;
1523 }
1524
1525 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1526 LIST_DEL(&tmp->list);
1527 free(tmp);
1528 }
1529 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001530 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001531 struct sockaddr_storage *sk;
1532 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001533 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001534 int arg = 0;
1535 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001536
William Lallemand1a748ae2015-05-19 16:37:23 +02001537 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1538 goto out;
1539
Willy Tarreaubaaee002006-06-26 02:48:02 +02001540 if (*(args[1]) == 0 || *(args[2]) == 0) {
1541 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001542 err_code |= ERR_ALERT | ERR_FATAL;
1543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001544 }
William Lallemand0f99e342011-10-12 17:50:54 +02001545
1546 logsrv = calloc(1, sizeof(struct logsrv));
1547
Willy Tarreau18324f52014-06-27 18:10:07 +02001548 /* just after the address, a length may be specified */
1549 if (strcmp(args[arg+2], "len") == 0) {
1550 len = atoi(args[arg+3]);
1551 if (len < 80 || len > 65535) {
1552 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1553 file, linenum, args[arg+3]);
1554 err_code |= ERR_ALERT | ERR_FATAL;
1555 goto out;
1556 }
1557 logsrv->maxlen = len;
1558
1559 /* skip these two args */
1560 arg += 2;
1561 }
1562 else
1563 logsrv->maxlen = MAX_SYSLOG_LEN;
1564
1565 if (logsrv->maxlen > global.max_syslog_len) {
1566 global.max_syslog_len = logsrv->maxlen;
1567 logline = realloc(logline, global.max_syslog_len + 1);
1568 }
1569
William Lallemand1a748ae2015-05-19 16:37:23 +02001570 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1571 goto out;
1572
Willy Tarreau18324f52014-06-27 18:10:07 +02001573 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001574 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001575 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001576 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001577 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001578 }
1579
William Lallemand0f99e342011-10-12 17:50:54 +02001580 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001581 if (*(args[arg+3])) {
1582 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001583 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001584 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001585 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001586 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001587 }
1588 }
1589
William Lallemand0f99e342011-10-12 17:50:54 +02001590 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001591 if (*(args[arg+4])) {
1592 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001593 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001594 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001595 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001596 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001597 }
1598 }
1599
Willy Tarreau902636f2013-03-10 19:44:48 +01001600 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001601 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001602 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001603 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001604 free(logsrv);
1605 goto out;
1606 }
1607 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001608
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001609 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001610 if (port1 != port2) {
1611 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1612 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001613 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001614 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001615 goto out;
1616 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001617
William Lallemand0f99e342011-10-12 17:50:54 +02001618 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001619 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001620 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001621 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622
William Lallemand0f99e342011-10-12 17:50:54 +02001623 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001624 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001625 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1626 char *name;
1627 int len;
1628
1629 if (global.log_send_hostname != NULL) {
1630 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1631 err_code |= ERR_ALERT;
1632 goto out;
1633 }
1634
1635 if (*(args[1]))
1636 name = args[1];
1637 else
1638 name = hostname;
1639
1640 len = strlen(name);
1641
1642 /* We'll add a space after the name to respect the log format */
1643 free(global.log_send_hostname);
1644 global.log_send_hostname = malloc(len + 2);
1645 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1646 }
Kevinm48936af2010-12-22 16:08:21 +00001647 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001648 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1649 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001650 if (*(args[1]) == 0) {
1651 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1652 err_code |= ERR_ALERT | ERR_FATAL;
1653 goto out;
1654 }
1655 free(global.log_tag);
1656 global.log_tag = strdup(args[1]);
1657 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001658 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001659 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1660 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001661 if (global.spread_checks != 0) {
1662 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001663 err_code |= ERR_ALERT;
1664 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001665 }
1666 if (*(args[1]) == 0) {
1667 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001668 err_code |= ERR_ALERT | ERR_FATAL;
1669 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001670 }
1671 global.spread_checks = atol(args[1]);
1672 if (global.spread_checks < 0 || global.spread_checks > 50) {
1673 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001674 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001676 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001677 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1678 const char *err;
1679 unsigned int val;
1680
William Lallemand1a748ae2015-05-19 16:37:23 +02001681 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1682 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001683 if (*(args[1]) == 0) {
1684 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1685 err_code |= ERR_ALERT | ERR_FATAL;
1686 goto out;
1687 }
1688
1689 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1690 if (err) {
1691 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1692 err_code |= ERR_ALERT | ERR_FATAL;
1693 }
1694 global.max_spread_checks = val;
1695 if (global.max_spread_checks < 0) {
1696 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1697 err_code |= ERR_ALERT | ERR_FATAL;
1698 }
1699 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001700 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1701#ifdef USE_CPU_AFFINITY
1702 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001703 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001704 unsigned long cpus = 0;
1705
1706 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001707 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001708 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001709 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001710 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001711 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001712 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001713 proc = atol(args[1]);
1714 if (proc >= 1 && proc <= LONGBITS)
1715 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001716 }
1717
1718 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001719 Alert("parsing [%s:%d]: %s expects a process number including 'all', 'odd', 'even', or a number from 1 to %d, followed by a list of CPU ranges with numbers from 0 to %d.\n",
1720 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001721 err_code |= ERR_ALERT | ERR_FATAL;
1722 goto out;
1723 }
1724
1725 cur_arg = 2;
1726 while (*args[cur_arg]) {
1727 unsigned int low, high;
1728
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001729 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001730 char *dash = strchr(args[cur_arg], '-');
1731
1732 low = high = str2uic(args[cur_arg]);
1733 if (dash)
1734 high = str2uic(dash + 1);
1735
1736 if (high < low) {
1737 unsigned int swap = low;
1738 low = high;
1739 high = swap;
1740 }
1741
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001742 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001743 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001744 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748
1749 while (low <= high)
1750 cpus |= 1UL << low++;
1751 }
1752 else {
1753 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1754 file, linenum, args[0], args[cur_arg]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
1758 cur_arg++;
1759 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001760 for (i = 0; i < LONGBITS; i++)
1761 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001762 global.cpu_map[i] = cpus;
1763#else
1764 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1765 err_code |= ERR_ALERT | ERR_FATAL;
1766 goto out;
1767#endif
1768 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001769 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001770 struct cfg_kw_list *kwl;
1771 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001772 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001773
1774 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1775 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1776 if (kwl->kw[index].section != CFG_GLOBAL)
1777 continue;
1778 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001779 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001780 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001781 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001782 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001783 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001784 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001785 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001786 err_code |= ERR_WARN;
1787 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001788 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001789 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001790 }
1791 }
1792 }
1793
Willy Tarreaubaaee002006-06-26 02:48:02 +02001794 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001795 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001796 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001797
Willy Tarreau058e9072009-07-20 09:30:05 +02001798 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001799 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001800 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001801}
1802
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001803void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001804{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001805 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001806 defproxy.mode = PR_MODE_TCP;
1807 defproxy.state = PR_STNEW;
1808 defproxy.maxconn = cfg_maxpconn;
1809 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001810 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001811
Simon Horman66183002013-02-23 10:16:43 +09001812 defproxy.defsrv.check.inter = DEF_CHKINTR;
1813 defproxy.defsrv.check.fastinter = 0;
1814 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001815 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1816 defproxy.defsrv.agent.fastinter = 0;
1817 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001818 defproxy.defsrv.check.rise = DEF_RISETIME;
1819 defproxy.defsrv.check.fall = DEF_FALLTIME;
1820 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1821 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001822 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001823 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001824 defproxy.defsrv.maxqueue = 0;
1825 defproxy.defsrv.minconn = 0;
1826 defproxy.defsrv.maxconn = 0;
1827 defproxy.defsrv.slowstart = 0;
1828 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1829 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1830 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001831
1832 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001833}
1834
Willy Tarreauade5ec42010-01-28 19:33:49 +01001835
Willy Tarreau63af98d2014-05-18 08:11:41 +02001836/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1837 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1838 * ERR_FATAL in case of error.
1839 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001840static int create_cond_regex_rule(const char *file, int line,
1841 struct proxy *px, int dir, int action, int flags,
1842 const char *cmd, const char *reg, const char *repl,
1843 const char **cond_start)
1844{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001845 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001846 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001847 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001848 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001849 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001850 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001851 int cs;
1852 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001853
1854 if (px == &defproxy) {
1855 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001856 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001857 goto err;
1858 }
1859
1860 if (*reg == 0) {
1861 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001862 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001863 goto err;
1864 }
1865
1866 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001867 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001868
Willy Tarreau5321c422010-01-28 20:35:13 +01001869 if (cond_start &&
1870 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001871 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1872 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1873 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001874 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001875 goto err;
1876 }
1877 }
1878 else if (cond_start && **cond_start) {
1879 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1880 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001881 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001882 goto err;
1883 }
1884
Willy Tarreau63af98d2014-05-18 08:11:41 +02001885 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001886 (dir == SMP_OPT_DIR_REQ) ?
1887 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1888 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1889 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001890
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001891 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001892 if (!preg) {
1893 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001894 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001895 goto err;
1896 }
1897
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001898 cs = !(flags & REG_ICASE);
1899 cap = !(flags & REG_NOSUB);
1900 error = NULL;
1901 if (!regex_comp(reg, preg, cs, cap, &error)) {
1902 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1903 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001904 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001905 goto err;
1906 }
1907
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001908 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001909 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001910 if (repl && err) {
1911 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1912 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001913 ret_code |= ERR_ALERT | ERR_FATAL;
1914 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001915 }
1916
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001917 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001918 ret_code |= ERR_WARN;
1919
1920 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001921
Willy Tarreau63af98d2014-05-18 08:11:41 +02001922 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001923 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001924 err:
1925 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001926 free(errmsg);
1927 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001928}
1929
Willy Tarreaubaaee002006-06-26 02:48:02 +02001930/*
William Lallemand51097192015-04-14 16:35:22 +02001931 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001932 * Returns the error code, 0 if OK, or any combination of :
1933 * - ERR_ABORT: must abort ASAP
1934 * - ERR_FATAL: we can continue parsing but not start the service
1935 * - ERR_WARN: a warning has been emitted
1936 * - ERR_ALERT: an alert has been emitted
1937 * Only the two first ones can stop processing, the two others are just
1938 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001939 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001940int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1941{
1942 static struct peers *curpeers = NULL;
1943 struct peer *newpeer = NULL;
1944 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001945 struct bind_conf *bind_conf;
1946 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001947 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001948 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001949
1950 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001951 if (!*args[1]) {
1952 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001953 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001954 goto out;
1955 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001956
William Lallemand6e62fb62015-04-28 16:55:23 +02001957 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1958 goto out;
1959
Emeric Brun32da3c42010-09-23 18:39:19 +02001960 err = invalid_char(args[1]);
1961 if (err) {
1962 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
1963 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01001964 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001965 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02001966 }
1967
1968 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
1969 /*
1970 * If there are two proxies with the same name only following
1971 * combinations are allowed:
1972 */
1973 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001974 Alert("Parsing [%s:%d]: peers section '%s' has the same name as another peers section declared at %s:%d.\n",
Emeric Brun32da3c42010-09-23 18:39:19 +02001975 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02001976 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001977 }
1978 }
1979
1980 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
1981 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
1982 err_code |= ERR_ALERT | ERR_ABORT;
1983 goto out;
1984 }
1985
1986 curpeers->next = peers;
1987 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02001988 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02001989 curpeers->conf.line = linenum;
1990 curpeers->last_change = now.tv_sec;
1991 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02001992 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02001993 }
1994 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01001995 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01001996 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01001997 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02001998
1999 if (!*args[2]) {
2000 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2001 file, linenum, args[0]);
2002 err_code |= ERR_ALERT | ERR_FATAL;
2003 goto out;
2004 }
2005
2006 err = invalid_char(args[1]);
2007 if (err) {
2008 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2009 file, linenum, *err, args[1]);
2010 err_code |= ERR_ALERT | ERR_FATAL;
2011 goto out;
2012 }
2013
2014 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2015 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2016 err_code |= ERR_ALERT | ERR_ABORT;
2017 goto out;
2018 }
2019
2020 /* the peers are linked backwards first */
2021 curpeers->count++;
2022 newpeer->next = curpeers->remote;
2023 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002024 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002025 newpeer->conf.line = linenum;
2026
2027 newpeer->last_change = now.tv_sec;
2028 newpeer->id = strdup(args[1]);
2029
Willy Tarreau902636f2013-03-10 19:44:48 +01002030 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002031 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002032 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002033 err_code |= ERR_ALERT | ERR_FATAL;
2034 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002035 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002036
2037 proto = protocol_by_family(sk->ss_family);
2038 if (!proto || !proto->connect) {
2039 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2040 file, linenum, args[0], args[1]);
2041 err_code |= ERR_ALERT | ERR_FATAL;
2042 goto out;
2043 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002044
2045 if (port1 != port2) {
2046 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2047 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002048 err_code |= ERR_ALERT | ERR_FATAL;
2049 goto out;
2050 }
2051
Willy Tarreau2aa38802013-02-20 19:20:59 +01002052 if (!port1) {
2053 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2054 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002055 err_code |= ERR_ALERT | ERR_FATAL;
2056 goto out;
2057 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002058
Emeric Brun32da3c42010-09-23 18:39:19 +02002059 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002060 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002061 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002062 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002063
Emeric Brun32da3c42010-09-23 18:39:19 +02002064 if (strcmp(newpeer->id, localpeer) == 0) {
2065 /* Current is local peer, it define a frontend */
2066 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002067 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002068
2069 if (!curpeers->peers_fe) {
2070 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2071 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2072 err_code |= ERR_ALERT | ERR_ABORT;
2073 goto out;
2074 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002075
Willy Tarreau237250c2011-07-29 01:49:03 +02002076 init_new_proxy(curpeers->peers_fe);
2077 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002078 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002079 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2080 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002081 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002082
2083 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2084
Willy Tarreau902636f2013-03-10 19:44:48 +01002085 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2086 if (errmsg && *errmsg) {
2087 indent_msg(&errmsg, 2);
2088 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002089 }
2090 else
2091 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2092 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002093 err_code |= ERR_FATAL;
2094 goto out;
2095 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002096
2097 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002098 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002099 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2100 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002101 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002102 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002103 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002104 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002105 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2106 global.maxsock += l->maxconn;
2107 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002108 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002109 else {
2110 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2111 file, linenum, args[0], args[1],
2112 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2113 err_code |= ERR_FATAL;
2114 goto out;
2115 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002116 }
2117 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002118 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2119 curpeers->state = PR_STSTOPPED;
2120 }
2121 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2122 curpeers->state = PR_STNEW;
2123 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002124 else if (*args[0] != 0) {
2125 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2126 err_code |= ERR_ALERT | ERR_FATAL;
2127 goto out;
2128 }
2129
2130out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002131 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002132 return err_code;
2133}
2134
Baptiste Assmann325137d2015-04-13 23:40:55 +02002135/*
2136 * Parse a <resolvers> section.
2137 * Returns the error code, 0 if OK, or any combination of :
2138 * - ERR_ABORT: must abort ASAP
2139 * - ERR_FATAL: we can continue parsing but not start the service
2140 * - ERR_WARN: a warning has been emitted
2141 * - ERR_ALERT: an alert has been emitted
2142 * Only the two first ones can stop processing, the two others are just
2143 * indicators.
2144 */
2145int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2146{
2147 static struct dns_resolvers *curr_resolvers = NULL;
2148 struct dns_nameserver *newnameserver = NULL;
2149 const char *err;
2150 int err_code = 0;
2151 char *errmsg = NULL;
2152
2153 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2154 if (!*args[1]) {
2155 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2156 err_code |= ERR_ALERT | ERR_ABORT;
2157 goto out;
2158 }
2159
2160 err = invalid_char(args[1]);
2161 if (err) {
2162 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2163 file, linenum, *err, args[0], args[1]);
2164 err_code |= ERR_ALERT | ERR_ABORT;
2165 goto out;
2166 }
2167
2168 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2169 /* Error if two resolvers owns the same name */
2170 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2171 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2172 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2173 err_code |= ERR_ALERT | ERR_ABORT;
2174 }
2175 }
2176
2177 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2178 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2179 err_code |= ERR_ALERT | ERR_ABORT;
2180 goto out;
2181 }
2182
2183 /* default values */
2184 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2185 curr_resolvers->conf.file = strdup(file);
2186 curr_resolvers->conf.line = linenum;
2187 curr_resolvers->id = strdup(args[1]);
2188 curr_resolvers->query_ids = EB_ROOT;
2189 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002190 curr_resolvers->hold.valid = 10000;
2191 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002192 curr_resolvers->resolve_retries = 3;
2193 LIST_INIT(&curr_resolvers->nameserver_list);
2194 LIST_INIT(&curr_resolvers->curr_resolution);
2195 }
2196 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2197 struct sockaddr_storage *sk;
2198 int port1, port2;
2199 struct protocol *proto;
2200
2201 if (!*args[2]) {
2202 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2203 file, linenum, args[0]);
2204 err_code |= ERR_ALERT | ERR_FATAL;
2205 goto out;
2206 }
2207
2208 err = invalid_char(args[1]);
2209 if (err) {
2210 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2211 file, linenum, *err, args[1]);
2212 err_code |= ERR_ALERT | ERR_FATAL;
2213 goto out;
2214 }
2215
2216 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2217 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2218 err_code |= ERR_ALERT | ERR_ABORT;
2219 goto out;
2220 }
2221
2222 /* the nameservers are linked backward first */
2223 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2224 curr_resolvers->count_nameservers++;
2225 newnameserver->resolvers = curr_resolvers;
2226 newnameserver->conf.file = strdup(file);
2227 newnameserver->conf.line = linenum;
2228 newnameserver->id = strdup(args[1]);
2229
2230 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2231 if (!sk) {
2232 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2233 err_code |= ERR_ALERT | ERR_FATAL;
2234 goto out;
2235 }
2236
2237 proto = protocol_by_family(sk->ss_family);
2238 if (!proto || !proto->connect) {
2239 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2240 file, linenum, args[0], args[1]);
2241 err_code |= ERR_ALERT | ERR_FATAL;
2242 goto out;
2243 }
2244
2245 if (port1 != port2) {
2246 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2247 file, linenum, args[0], args[1], args[2]);
2248 err_code |= ERR_ALERT | ERR_FATAL;
2249 goto out;
2250 }
2251
2252 newnameserver->addr = *sk;
2253 }
2254 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2255 const char *res;
2256 unsigned int time;
2257
2258 if (!*args[2]) {
2259 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2260 file, linenum, args[0]);
2261 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2262 err_code |= ERR_ALERT | ERR_FATAL;
2263 goto out;
2264 }
2265 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2266 if (res) {
2267 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2268 file, linenum, *res, args[0]);
2269 err_code |= ERR_ALERT | ERR_FATAL;
2270 goto out;
2271 }
2272 if (strcmp(args[1], "valid") == 0)
2273 curr_resolvers->hold.valid = time;
2274 else {
2275 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2276 file, linenum, args[0], args[1]);
2277 err_code |= ERR_ALERT | ERR_FATAL;
2278 goto out;
2279 }
2280
2281 }
2282 else if (strcmp(args[0], "resolve_retries") == 0) {
2283 if (!*args[1]) {
2284 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2285 file, linenum, args[0]);
2286 err_code |= ERR_ALERT | ERR_FATAL;
2287 goto out;
2288 }
2289 curr_resolvers->resolve_retries = atoi(args[1]);
2290 }
2291 else if (strcmp(args[0], "timeout") == 0) {
2292 const char *res;
2293 unsigned int timeout_retry;
2294
2295 if (!*args[2]) {
2296 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2297 file, linenum, args[0]);
2298 err_code |= ERR_ALERT | ERR_FATAL;
2299 goto out;
2300 }
2301 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2302 if (res) {
2303 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2304 file, linenum, *res, args[0]);
2305 err_code |= ERR_ALERT | ERR_FATAL;
2306 goto out;
2307 }
2308 curr_resolvers->timeout.retry = timeout_retry;
2309 } /* neither "nameserver" nor "resolvers" */
2310 else if (*args[0] != 0) {
2311 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2312 err_code |= ERR_ALERT | ERR_FATAL;
2313 goto out;
2314 }
2315
2316 out:
2317 free(errmsg);
2318 return err_code;
2319}
Simon Horman0d16a402015-01-30 11:22:58 +09002320
2321/*
William Lallemand51097192015-04-14 16:35:22 +02002322 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002323 * Returns the error code, 0 if OK, or any combination of :
2324 * - ERR_ABORT: must abort ASAP
2325 * - ERR_FATAL: we can continue parsing but not start the service
2326 * - ERR_WARN: a warning has been emitted
2327 * - ERR_ALERT: an alert has been emitted
2328 * Only the two first ones can stop processing, the two others are just
2329 * indicators.
2330 */
2331int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2332{
2333 static struct mailers *curmailers = NULL;
2334 struct mailer *newmailer = NULL;
2335 const char *err;
2336 int err_code = 0;
2337 char *errmsg = NULL;
2338
2339 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2340 if (!*args[1]) {
2341 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2342 err_code |= ERR_ALERT | ERR_ABORT;
2343 goto out;
2344 }
2345
2346 err = invalid_char(args[1]);
2347 if (err) {
2348 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2349 file, linenum, *err, args[0], args[1]);
2350 err_code |= ERR_ALERT | ERR_ABORT;
2351 goto out;
2352 }
2353
2354 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2355 /*
2356 * If there are two proxies with the same name only following
2357 * combinations are allowed:
2358 */
2359 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002360 Alert("Parsing [%s:%d]: mailers section '%s' has the same name as another mailers section declared at %s:%d.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002361 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002363 }
2364 }
2365
2366 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2367 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2368 err_code |= ERR_ALERT | ERR_ABORT;
2369 goto out;
2370 }
2371
2372 curmailers->next = mailers;
2373 mailers = curmailers;
2374 curmailers->conf.file = strdup(file);
2375 curmailers->conf.line = linenum;
2376 curmailers->id = strdup(args[1]);
2377 }
2378 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2379 struct sockaddr_storage *sk;
2380 int port1, port2;
2381 struct protocol *proto;
2382
2383 if (!*args[2]) {
2384 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2385 file, linenum, args[0]);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
2389
2390 err = invalid_char(args[1]);
2391 if (err) {
2392 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2393 file, linenum, *err, args[1]);
2394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
2396 }
2397
2398 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2399 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2400 err_code |= ERR_ALERT | ERR_ABORT;
2401 goto out;
2402 }
2403
2404 /* the mailers are linked backwards first */
2405 curmailers->count++;
2406 newmailer->next = curmailers->mailer_list;
2407 curmailers->mailer_list = newmailer;
2408 newmailer->mailers = curmailers;
2409 newmailer->conf.file = strdup(file);
2410 newmailer->conf.line = linenum;
2411
2412 newmailer->id = strdup(args[1]);
2413
2414 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2415 if (!sk) {
2416 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2417 err_code |= ERR_ALERT | ERR_FATAL;
2418 goto out;
2419 }
2420
2421 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002422 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2423 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002424 file, linenum, args[0], args[1]);
2425 err_code |= ERR_ALERT | ERR_FATAL;
2426 goto out;
2427 }
2428
2429 if (port1 != port2) {
2430 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2431 file, linenum, args[0], args[1], args[2]);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435
2436 if (!port1) {
2437 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2438 file, linenum, args[0], args[1], args[2]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442
2443 newmailer->addr = *sk;
2444 newmailer->proto = proto;
2445 newmailer->xprt = &raw_sock;
2446 newmailer->sock_init_arg = NULL;
2447 } /* neither "mailer" nor "mailers" */
2448 else if (*args[0] != 0) {
2449 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2450 err_code |= ERR_ALERT | ERR_FATAL;
2451 goto out;
2452 }
2453
2454out:
2455 free(errmsg);
2456 return err_code;
2457}
2458
Simon Horman9dc49962015-01-30 11:22:59 +09002459static void free_email_alert(struct proxy *p)
2460{
2461 free(p->email_alert.mailers.name);
2462 p->email_alert.mailers.name = NULL;
2463 free(p->email_alert.from);
2464 p->email_alert.from = NULL;
2465 free(p->email_alert.to);
2466 p->email_alert.to = NULL;
2467 free(p->email_alert.myhostname);
2468 p->email_alert.myhostname = NULL;
2469}
2470
Willy Tarreau3842f002009-06-14 11:39:52 +02002471int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002472{
2473 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002474 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002475 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002476 int rc;
2477 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002478 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002479 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002480 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002481 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002482 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002483
Willy Tarreau977b8e42006-12-29 14:19:17 +01002484 if (!strcmp(args[0], "listen"))
2485 rc = PR_CAP_LISTEN;
2486 else if (!strcmp(args[0], "frontend"))
2487 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002488 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002489 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002490 else
2491 rc = PR_CAP_NONE;
2492
2493 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002494 if (!*args[1]) {
2495 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2496 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2497 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002498 err_code |= ERR_ALERT | ERR_ABORT;
2499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002501
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002502 err = invalid_char(args[1]);
2503 if (err) {
2504 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2505 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002506 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002507 }
2508
Willy Tarreau8f50b682015-05-26 11:45:02 +02002509 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2510 if (curproxy) {
2511 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2512 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2513 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002514 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002515 }
2516
Willy Tarreaubaaee002006-06-26 02:48:02 +02002517 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2518 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002519 err_code |= ERR_ALERT | ERR_ABORT;
2520 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002521 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002522
Willy Tarreau97cb7802010-01-03 20:23:58 +01002523 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002524 curproxy->next = proxy;
2525 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002526 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2527 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002528 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002529 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002530 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002531 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002532
William Lallemand6e62fb62015-04-28 16:55:23 +02002533 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2534 if (curproxy->cap & PR_CAP_FE)
2535 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2536 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002537 }
2538
2539 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002540 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002541 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002542
Willy Tarreaubaaee002006-06-26 02:48:02 +02002543 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002544 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002545 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002546 curproxy->no_options = defproxy.no_options;
2547 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002548 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002549 curproxy->except_net = defproxy.except_net;
2550 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002551 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002552 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002553
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002554 if (defproxy.fwdfor_hdr_len) {
2555 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2556 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2557 }
2558
Willy Tarreaub86db342009-11-30 11:50:16 +01002559 if (defproxy.orgto_hdr_len) {
2560 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2561 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2562 }
2563
Mark Lamourinec2247f02012-01-04 13:02:01 -05002564 if (defproxy.server_id_hdr_len) {
2565 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2566 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2567 }
2568
Willy Tarreau977b8e42006-12-29 14:19:17 +01002569 if (curproxy->cap & PR_CAP_FE) {
2570 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002571 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002572 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002573
2574 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002575 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2576 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002577
2578 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2579 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002580
Willy Tarreau977b8e42006-12-29 14:19:17 +01002581 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002582 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002583 curproxy->fullconn = defproxy.fullconn;
2584 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002585 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002586 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002587
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002588 if (defproxy.check_req) {
2589 curproxy->check_req = calloc(1, defproxy.check_len);
2590 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2591 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002592 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002593
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002594 if (defproxy.expect_str) {
2595 curproxy->expect_str = strdup(defproxy.expect_str);
2596 if (defproxy.expect_regex) {
2597 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002598 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2599 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002600 }
2601 }
2602
Willy Tarreau67402132012-05-31 20:40:20 +02002603 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002604 if (defproxy.cookie_name)
2605 curproxy->cookie_name = strdup(defproxy.cookie_name);
2606 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002607 if (defproxy.cookie_domain)
2608 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002609
Willy Tarreau31936852010-10-06 16:59:56 +02002610 if (defproxy.cookie_maxidle)
2611 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2612
2613 if (defproxy.cookie_maxlife)
2614 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2615
Emeric Brun647caf12009-06-30 17:57:00 +02002616 if (defproxy.rdp_cookie_name)
2617 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2618 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2619
Willy Tarreau01732802007-11-01 22:48:15 +01002620 if (defproxy.url_param_name)
2621 curproxy->url_param_name = strdup(defproxy.url_param_name);
2622 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002623
Benoitaffb4812009-03-25 13:02:10 +01002624 if (defproxy.hh_name)
2625 curproxy->hh_name = strdup(defproxy.hh_name);
2626 curproxy->hh_len = defproxy.hh_len;
2627 curproxy->hh_match_domain = defproxy.hh_match_domain;
2628
Willy Tarreauef9a3602012-12-08 22:29:20 +01002629 if (defproxy.conn_src.iface_name)
2630 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2631 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002632 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002633#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002634 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002635#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002636 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002637
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002638 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002639 if (defproxy.capture_name)
2640 curproxy->capture_name = strdup(defproxy.capture_name);
2641 curproxy->capture_namelen = defproxy.capture_namelen;
2642 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002643 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002644
Willy Tarreau977b8e42006-12-29 14:19:17 +01002645 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002646 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002647 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002648 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002649 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002650 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651 curproxy->mon_net = defproxy.mon_net;
2652 curproxy->mon_mask = defproxy.mon_mask;
2653 if (defproxy.monitor_uri)
2654 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2655 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002656 if (defproxy.defbe.name)
2657 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002658
2659 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002660 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2661 if (curproxy->conf.logformat_string &&
2662 curproxy->conf.logformat_string != default_http_log_format &&
2663 curproxy->conf.logformat_string != default_tcp_log_format &&
2664 curproxy->conf.logformat_string != clf_http_log_format)
2665 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2666
2667 if (defproxy.conf.lfs_file) {
2668 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2669 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2670 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002671 }
2672
2673 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002674 curproxy->timeout.connect = defproxy.timeout.connect;
2675 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002676 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002677 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002678 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002679 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002680 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002681 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002682 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002683 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002684 }
2685
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002687 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002688
2689 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002690 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002691 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002692 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002693 LIST_INIT(&node->list);
2694 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2695 }
2696
Willy Tarreau62a61232013-04-12 18:13:46 +02002697 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2698 if (curproxy->conf.uniqueid_format_string)
2699 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2700
Willy Tarreau094af4e2015-01-07 15:03:42 +01002701 if (defproxy.log_tag)
2702 curproxy->log_tag = strdup(defproxy.log_tag);
2703
Willy Tarreau62a61232013-04-12 18:13:46 +02002704 if (defproxy.conf.uif_file) {
2705 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2706 curproxy->conf.uif_line = defproxy.conf.uif_line;
2707 }
William Lallemanda73203e2012-03-12 12:48:57 +01002708
2709 /* copy default header unique id */
2710 if (defproxy.header_unique_id)
2711 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2712
William Lallemand82fe75c2012-10-23 10:25:10 +02002713 /* default compression options */
2714 if (defproxy.comp != NULL) {
2715 curproxy->comp = calloc(1, sizeof(struct comp));
2716 curproxy->comp->algos = defproxy.comp->algos;
2717 curproxy->comp->types = defproxy.comp->types;
2718 }
2719
Willy Tarreaubaaee002006-06-26 02:48:02 +02002720 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002721 curproxy->conf.used_listener_id = EB_ROOT;
2722 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002723
Simon Horman98637e52014-06-20 12:30:16 +09002724 if (defproxy.check_path)
2725 curproxy->check_path = strdup(defproxy.check_path);
2726 if (defproxy.check_command)
2727 curproxy->check_command = strdup(defproxy.check_command);
2728
Simon Horman9dc49962015-01-30 11:22:59 +09002729 if (defproxy.email_alert.mailers.name)
2730 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2731 if (defproxy.email_alert.from)
2732 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2733 if (defproxy.email_alert.to)
2734 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2735 if (defproxy.email_alert.myhostname)
2736 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002737 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002738
Willy Tarreau93893792009-07-23 13:19:11 +02002739 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002740 }
2741 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2742 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002743 /* FIXME-20070101: we should do this too at the end of the
2744 * config parsing to free all default values.
2745 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002746 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2747 err_code |= ERR_ABORT;
2748 goto out;
2749 }
2750
Willy Tarreaua534fea2008-08-03 12:19:50 +02002751 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002752 free(defproxy.check_command);
2753 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002754 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002755 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002756 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002757 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002758 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002759 free(defproxy.capture_name);
2760 free(defproxy.monitor_uri);
2761 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002762 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002763 free(defproxy.fwdfor_hdr_name);
2764 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002765 free(defproxy.orgto_hdr_name);
2766 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002767 free(defproxy.server_id_hdr_name);
2768 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002769 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002770 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002771 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002772 free(defproxy.expect_regex);
2773 defproxy.expect_regex = NULL;
2774 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002775
Willy Tarreau62a61232013-04-12 18:13:46 +02002776 if (defproxy.conf.logformat_string != default_http_log_format &&
2777 defproxy.conf.logformat_string != default_tcp_log_format &&
2778 defproxy.conf.logformat_string != clf_http_log_format)
2779 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002780
Willy Tarreau62a61232013-04-12 18:13:46 +02002781 free(defproxy.conf.uniqueid_format_string);
2782 free(defproxy.conf.lfs_file);
2783 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002784 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002785 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002786
Willy Tarreaua534fea2008-08-03 12:19:50 +02002787 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002788 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002789
Willy Tarreaubaaee002006-06-26 02:48:02 +02002790 /* we cannot free uri_auth because it might already be used */
2791 init_default_instance();
2792 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002793 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2794 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002796 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002797 }
2798 else if (curproxy == NULL) {
2799 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002800 err_code |= ERR_ALERT | ERR_FATAL;
2801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002803
2804 /* update the current file and line being parsed */
2805 curproxy->conf.args.file = curproxy->conf.file;
2806 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002807
2808 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002809 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2810 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2811 if (err_code & ERR_FATAL)
2812 goto out;
2813 }
2814 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002815 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002816 int cur_arg;
2817
Willy Tarreaubaaee002006-06-26 02:48:02 +02002818 if (curproxy == &defproxy) {
2819 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002820 err_code |= ERR_ALERT | ERR_FATAL;
2821 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002822 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002823 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002824 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002825
Willy Tarreau24709282013-03-10 21:32:12 +01002826 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002827 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002828 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002829 err_code |= ERR_ALERT | ERR_FATAL;
2830 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002831 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002832
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002833 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002834
2835 /* use default settings for unix sockets */
2836 bind_conf->ux.uid = global.unix_bind.ux.uid;
2837 bind_conf->ux.gid = global.unix_bind.ux.gid;
2838 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002839
2840 /* NOTE: the following line might create several listeners if there
2841 * are comma-separated IPs or port ranges. So all further processing
2842 * will have to be applied to all listeners created after last_listen.
2843 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002844 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2845 if (errmsg && *errmsg) {
2846 indent_msg(&errmsg, 2);
2847 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002848 }
2849 else
2850 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2851 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002852 err_code |= ERR_ALERT | ERR_FATAL;
2853 goto out;
2854 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002855
Willy Tarreau4348fad2012-09-20 16:48:07 +02002856 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2857 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002858 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002859 }
2860
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002861 cur_arg = 2;
2862 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002863 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002864 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002865 char *err;
2866
Willy Tarreau26982662012-09-12 23:17:10 +02002867 kw = bind_find_kw(args[cur_arg]);
2868 if (kw) {
2869 char *err = NULL;
2870 int code;
2871
2872 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002873 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2874 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002875 cur_arg += 1 + kw->skip ;
2876 err_code |= ERR_ALERT | ERR_FATAL;
2877 goto out;
2878 }
2879
Willy Tarreau4348fad2012-09-20 16:48:07 +02002880 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002881 err_code |= code;
2882
2883 if (code) {
2884 if (err && *err) {
2885 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002886 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002887 }
2888 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002889 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2890 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002891 if (code & ERR_FATAL) {
2892 free(err);
2893 cur_arg += 1 + kw->skip;
2894 goto out;
2895 }
2896 }
2897 free(err);
2898 cur_arg += 1 + kw->skip;
2899 continue;
2900 }
2901
Willy Tarreau8638f482012-09-18 18:01:17 +02002902 err = NULL;
2903 if (!bind_dumped) {
2904 bind_dump_kws(&err);
2905 indent_msg(&err, 4);
2906 bind_dumped = 1;
2907 }
2908
2909 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2910 file, linenum, args[0], args[1], args[cur_arg],
2911 err ? " Registered keywords :" : "", err ? err : "");
2912 free(err);
2913
Willy Tarreau93893792009-07-23 13:19:11 +02002914 err_code |= ERR_ALERT | ERR_FATAL;
2915 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002916 }
Willy Tarreau93893792009-07-23 13:19:11 +02002917 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002918 }
2919 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002920 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002921 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2922 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002923 err_code |= ERR_ALERT | ERR_FATAL;
2924 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002925 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002926 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002927 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002928
Willy Tarreaubaaee002006-06-26 02:48:02 +02002929 /* flush useless bits */
2930 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002931 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002932 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002933 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002934 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002935 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002936
William Lallemanddf1425a2015-04-28 20:17:49 +02002937 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2938 goto out;
2939
Willy Tarreau1c47f852006-07-09 08:22:27 +02002940 if (!*args[1]) {
2941 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2942 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002943 err_code |= ERR_ALERT | ERR_FATAL;
2944 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002945 }
2946
Willy Tarreaua534fea2008-08-03 12:19:50 +02002947 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002948 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002949 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002950 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002951 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2952
Willy Tarreau93893792009-07-23 13:19:11 +02002953 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002954 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002956 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2957 goto out;
2958
Willy Tarreaubaaee002006-06-26 02:48:02 +02002959 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2960 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2961 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2962 else {
2963 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
2965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002968 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002969 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002970
2971 if (curproxy == &defproxy) {
2972 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2973 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002974 err_code |= ERR_ALERT | ERR_FATAL;
2975 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002976 }
2977
William Lallemanddf1425a2015-04-28 20:17:49 +02002978 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2979 goto out;
2980
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002981 if (!*args[1]) {
2982 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2983 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002984 err_code |= ERR_ALERT | ERR_FATAL;
2985 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002986 }
2987
2988 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002989 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002990 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002991
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002992 if (curproxy->uuid <= 0) {
2993 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002994 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002995 err_code |= ERR_ALERT | ERR_FATAL;
2996 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002997 }
2998
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002999 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3000 if (node) {
3001 struct proxy *target = container_of(node, struct proxy, conf.id);
3002 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3003 file, linenum, proxy_type_str(curproxy), curproxy->id,
3004 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3005 err_code |= ERR_ALERT | ERR_FATAL;
3006 goto out;
3007 }
3008 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003009 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003010 else if (!strcmp(args[0], "description")) {
3011 int i, len=0;
3012 char *d;
3013
Cyril Bonté99ed3272010-01-24 23:29:44 +01003014 if (curproxy == &defproxy) {
3015 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3016 file, linenum, args[0]);
3017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
3020
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003021 if (!*args[1]) {
3022 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3023 file, linenum, args[0]);
3024 return -1;
3025 }
3026
Willy Tarreau348acfe2014-04-14 15:00:39 +02003027 for (i = 1; *args[i]; i++)
3028 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003029
3030 d = (char *)calloc(1, len);
3031 curproxy->desc = d;
3032
Willy Tarreau348acfe2014-04-14 15:00:39 +02003033 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3034 for (i = 2; *args[i]; i++)
3035 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003036
3037 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003038 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003039 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3040 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003041 curproxy->state = PR_STSTOPPED;
3042 }
3043 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003044 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3045 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003046 curproxy->state = PR_STNEW;
3047 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003048 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3049 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003050 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003051
3052 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003053 unsigned int low, high;
3054
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003055 if (strcmp(args[cur_arg], "all") == 0) {
3056 set = 0;
3057 break;
3058 }
3059 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003060 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003061 }
3062 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003063 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003064 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003065 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003066 char *dash = strchr(args[cur_arg], '-');
3067
3068 low = high = str2uic(args[cur_arg]);
3069 if (dash)
3070 high = str2uic(dash + 1);
3071
3072 if (high < low) {
3073 unsigned int swap = low;
3074 low = high;
3075 high = swap;
3076 }
3077
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003078 if (low < 1 || high > LONGBITS) {
3079 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3080 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003081 err_code |= ERR_ALERT | ERR_FATAL;
3082 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003083 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003084 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003085 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003086 }
3087 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003088 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3089 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003090 err_code |= ERR_ALERT | ERR_FATAL;
3091 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003092 }
3093 cur_arg++;
3094 }
3095 curproxy->bind_proc = set;
3096 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003097 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003098 if (curproxy == &defproxy) {
3099 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_ALERT | ERR_FATAL;
3101 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003102 }
3103
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003104 err = invalid_char(args[1]);
3105 if (err) {
3106 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3107 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003109 }
3110
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003111 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003112 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3113 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003114 err_code |= ERR_ALERT | ERR_FATAL;
3115 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003116 }
3117 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003118 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3119 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120
Willy Tarreau977b8e42006-12-29 14:19:17 +01003121 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003122 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003123
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 if (*(args[1]) == 0) {
3125 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3126 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003127 err_code |= ERR_ALERT | ERR_FATAL;
3128 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003129 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003130
Willy Tarreau67402132012-05-31 20:40:20 +02003131 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003132 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003133 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003134 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003135 curproxy->cookie_name = strdup(args[1]);
3136 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003137
Willy Tarreaubaaee002006-06-26 02:48:02 +02003138 cur_arg = 2;
3139 while (*(args[cur_arg])) {
3140 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003141 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003142 }
3143 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003144 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003145 }
3146 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003147 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
3149 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003150 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 }
3152 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003153 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003154 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003155 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003156 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003157 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003158 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003159 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003160 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003161 else if (!strcmp(args[cur_arg], "httponly")) {
3162 curproxy->ck_opts |= PR_CK_HTTPONLY;
3163 }
3164 else if (!strcmp(args[cur_arg], "secure")) {
3165 curproxy->ck_opts |= PR_CK_SECURE;
3166 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003167 else if (!strcmp(args[cur_arg], "domain")) {
3168 if (!*args[cur_arg + 1]) {
3169 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3170 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003171 err_code |= ERR_ALERT | ERR_FATAL;
3172 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003173 }
3174
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003175 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003176 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003177 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3178 " dots nor does not start with a dot."
3179 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003180 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003181 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003182 }
3183
3184 err = invalid_domainchar(args[cur_arg + 1]);
3185 if (err) {
3186 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3187 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003188 err_code |= ERR_ALERT | ERR_FATAL;
3189 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003190 }
3191
Willy Tarreau68a897b2009-12-03 23:28:34 +01003192 if (!curproxy->cookie_domain) {
3193 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3194 } else {
3195 /* one domain was already specified, add another one by
3196 * building the string which will be returned along with
3197 * the cookie.
3198 */
3199 char *new_ptr;
3200 int new_len = strlen(curproxy->cookie_domain) +
3201 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3202 new_ptr = malloc(new_len);
3203 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3204 free(curproxy->cookie_domain);
3205 curproxy->cookie_domain = new_ptr;
3206 }
Willy Tarreau31936852010-10-06 16:59:56 +02003207 cur_arg++;
3208 }
3209 else if (!strcmp(args[cur_arg], "maxidle")) {
3210 unsigned int maxidle;
3211 const char *res;
3212
3213 if (!*args[cur_arg + 1]) {
3214 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3215 file, linenum, args[cur_arg]);
3216 err_code |= ERR_ALERT | ERR_FATAL;
3217 goto out;
3218 }
3219
3220 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3221 if (res) {
3222 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3223 file, linenum, *res, args[cur_arg]);
3224 err_code |= ERR_ALERT | ERR_FATAL;
3225 goto out;
3226 }
3227 curproxy->cookie_maxidle = maxidle;
3228 cur_arg++;
3229 }
3230 else if (!strcmp(args[cur_arg], "maxlife")) {
3231 unsigned int maxlife;
3232 const char *res;
3233
3234 if (!*args[cur_arg + 1]) {
3235 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3236 file, linenum, args[cur_arg]);
3237 err_code |= ERR_ALERT | ERR_FATAL;
3238 goto out;
3239 }
3240
3241 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3242 if (res) {
3243 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3244 file, linenum, *res, args[cur_arg]);
3245 err_code |= ERR_ALERT | ERR_FATAL;
3246 goto out;
3247 }
3248 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003249 cur_arg++;
3250 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003251 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003252 Alert("parsing [%s:%d] : '%s' supports 'rewrite', 'insert', 'prefix', 'indirect', 'nocache', 'postonly', 'domain', 'maxidle, and 'maxlife' options.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003253 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003254 err_code |= ERR_ALERT | ERR_FATAL;
3255 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003256 }
3257 cur_arg++;
3258 }
Willy Tarreau67402132012-05-31 20:40:20 +02003259 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003260 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3261 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003262 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003263 }
3264
Willy Tarreau67402132012-05-31 20:40:20 +02003265 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003266 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3267 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003268 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003269 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003270
Willy Tarreau67402132012-05-31 20:40:20 +02003271 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003272 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3273 file, linenum);
3274 err_code |= ERR_ALERT | ERR_FATAL;
3275 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003277 else if (!strcmp(args[0], "email-alert")) {
3278 if (*(args[1]) == 0) {
3279 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3280 file, linenum, args[0]);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283 }
3284
3285 if (!strcmp(args[1], "from")) {
3286 if (*(args[1]) == 0) {
3287 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3288 file, linenum, args[1]);
3289 err_code |= ERR_ALERT | ERR_FATAL;
3290 goto out;
3291 }
3292 free(curproxy->email_alert.from);
3293 curproxy->email_alert.from = strdup(args[2]);
3294 }
3295 else if (!strcmp(args[1], "mailers")) {
3296 if (*(args[1]) == 0) {
3297 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3298 file, linenum, args[1]);
3299 err_code |= ERR_ALERT | ERR_FATAL;
3300 goto out;
3301 }
3302 free(curproxy->email_alert.mailers.name);
3303 curproxy->email_alert.mailers.name = strdup(args[2]);
3304 }
3305 else if (!strcmp(args[1], "myhostname")) {
3306 if (*(args[1]) == 0) {
3307 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3308 file, linenum, args[1]);
3309 err_code |= ERR_ALERT | ERR_FATAL;
3310 goto out;
3311 }
3312 free(curproxy->email_alert.myhostname);
3313 curproxy->email_alert.myhostname = strdup(args[2]);
3314 }
Simon Horman64e34162015-02-06 11:11:57 +09003315 else if (!strcmp(args[1], "level")) {
3316 curproxy->email_alert.level = get_log_level(args[2]);
3317 if (curproxy->email_alert.level < 0) {
3318 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3319 file, linenum, args[1], args[2]);
3320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
3322 }
3323 }
Simon Horman9dc49962015-01-30 11:22:59 +09003324 else if (!strcmp(args[1], "to")) {
3325 if (*(args[1]) == 0) {
3326 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3327 file, linenum, args[1]);
3328 err_code |= ERR_ALERT | ERR_FATAL;
3329 goto out;
3330 }
3331 free(curproxy->email_alert.to);
3332 curproxy->email_alert.to = strdup(args[2]);
3333 }
3334 else {
3335 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3336 file, linenum, args[1]);
3337 err_code |= ERR_ALERT | ERR_FATAL;
3338 goto out;
3339 }
Simon Horman64e34162015-02-06 11:11:57 +09003340 /* Indicate that the email_alert is at least partially configured */
3341 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003342 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003343 else if (!strcmp(args[0], "external-check")) {
3344 if (*(args[1]) == 0) {
3345 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3346 file, linenum, args[0]);
3347 err_code |= ERR_ALERT | ERR_FATAL;
3348 goto out;
3349 }
3350
3351 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003352 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3353 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003354 if (*(args[1]) == 0) {
3355 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3356 file, linenum, args[1]);
3357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
3359 }
3360 free(curproxy->check_command);
3361 curproxy->check_command = strdup(args[2]);
3362 }
3363 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003364 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3365 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003366 if (*(args[1]) == 0) {
3367 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3368 file, linenum, args[1]);
3369 err_code |= ERR_ALERT | ERR_FATAL;
3370 goto out;
3371 }
3372 free(curproxy->check_path);
3373 curproxy->check_path = strdup(args[2]);
3374 }
3375 else {
3376 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3377 file, linenum, args[1]);
3378 err_code |= ERR_ALERT | ERR_FATAL;
3379 goto out;
3380 }
3381 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003382 else if (!strcmp(args[0], "persist")) { /* persist */
3383 if (*(args[1]) == 0) {
3384 Alert("parsing [%s:%d] : missing persist method.\n",
3385 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003386 err_code |= ERR_ALERT | ERR_FATAL;
3387 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003388 }
3389
3390 if (!strncmp(args[1], "rdp-cookie", 10)) {
3391 curproxy->options2 |= PR_O2_RDPC_PRST;
3392
Emeric Brunb982a3d2010-01-04 15:45:53 +01003393 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003394 const char *beg, *end;
3395
3396 beg = args[1] + 11;
3397 end = strchr(beg, ')');
3398
William Lallemanddf1425a2015-04-28 20:17:49 +02003399 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3400 goto out;
3401
Emeric Brun647caf12009-06-30 17:57:00 +02003402 if (!end || end == beg) {
3403 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3404 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003405 err_code |= ERR_ALERT | ERR_FATAL;
3406 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003407 }
3408
3409 free(curproxy->rdp_cookie_name);
3410 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3411 curproxy->rdp_cookie_len = end-beg;
3412 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003413 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003414 free(curproxy->rdp_cookie_name);
3415 curproxy->rdp_cookie_name = strdup("msts");
3416 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3417 }
3418 else { /* syntax */
3419 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3420 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003421 err_code |= ERR_ALERT | ERR_FATAL;
3422 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003423 }
3424 }
3425 else {
3426 Alert("parsing [%s:%d] : unknown persist method.\n",
3427 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003428 err_code |= ERR_ALERT | ERR_FATAL;
3429 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003430 }
3431 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003432 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003433 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003435 if (curproxy == &defproxy) {
3436 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3437 err_code |= ERR_ALERT | ERR_FATAL;
3438 goto out;
3439 }
3440
Willy Tarreau977b8e42006-12-29 14:19:17 +01003441 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003442 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003443
Willy Tarreaubaaee002006-06-26 02:48:02 +02003444 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003445 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003446 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 }
3450 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003451 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003452 curproxy->appsession_name = strdup(args[1]);
3453 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3454 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003455 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3456 if (err) {
3457 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3458 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003461 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003462 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003463
Willy Tarreau51041c72007-09-09 21:56:53 +02003464 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3465 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003466 err_code |= ERR_ALERT | ERR_ABORT;
3467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003468 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003469
3470 cur_arg = 6;
3471 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003472 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3473 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003474 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003475 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003476 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003477 } else if (!strcmp(args[cur_arg], "prefix")) {
3478 curproxy->options2 |= PR_O2_AS_PFX;
3479 } else if (!strcmp(args[cur_arg], "mode")) {
3480 if (!*args[cur_arg + 1]) {
3481 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3482 file, linenum, args[0], args[cur_arg]);
3483 err_code |= ERR_ALERT | ERR_FATAL;
3484 goto out;
3485 }
3486
3487 cur_arg++;
3488 if (!strcmp(args[cur_arg], "query-string")) {
3489 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3490 curproxy->options2 |= PR_O2_AS_M_QS;
3491 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3492 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3493 curproxy->options2 |= PR_O2_AS_M_PP;
3494 } else {
3495 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3496 err_code |= ERR_ALERT | ERR_FATAL;
3497 goto out;
3498 }
3499 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003500 cur_arg++;
3501 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003502 } /* Url App Session */
3503 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003504 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003505 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003506
Willy Tarreaubaaee002006-06-26 02:48:02 +02003507 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003508 if (curproxy == &defproxy) {
3509 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3510 err_code |= ERR_ALERT | ERR_FATAL;
3511 goto out;
3512 }
3513
William Lallemand1a748ae2015-05-19 16:37:23 +02003514 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3515 goto out;
3516
Willy Tarreaubaaee002006-06-26 02:48:02 +02003517 if (*(args[4]) == 0) {
3518 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3519 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003520 err_code |= ERR_ALERT | ERR_FATAL;
3521 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003522 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003523 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003524 curproxy->capture_name = strdup(args[2]);
3525 curproxy->capture_namelen = strlen(curproxy->capture_name);
3526 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 curproxy->to_log |= LW_COOKIE;
3528 }
3529 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3530 struct cap_hdr *hdr;
3531
3532 if (curproxy == &defproxy) {
3533 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 +02003534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 }
3537
William Lallemand1a748ae2015-05-19 16:37:23 +02003538 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3539 goto out;
3540
Willy Tarreaubaaee002006-06-26 02:48:02 +02003541 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3542 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3543 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
3545 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003546 }
3547
3548 hdr = calloc(sizeof(struct cap_hdr), 1);
3549 hdr->next = curproxy->req_cap;
3550 hdr->name = strdup(args[3]);
3551 hdr->namelen = strlen(args[3]);
3552 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003553 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003554 hdr->index = curproxy->nb_req_cap++;
3555 curproxy->req_cap = hdr;
3556 curproxy->to_log |= LW_REQHDR;
3557 }
3558 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3559 struct cap_hdr *hdr;
3560
3561 if (curproxy == &defproxy) {
3562 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 +02003563 err_code |= ERR_ALERT | ERR_FATAL;
3564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003565 }
3566
William Lallemand1a748ae2015-05-19 16:37:23 +02003567 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3568 goto out;
3569
Willy Tarreaubaaee002006-06-26 02:48:02 +02003570 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3571 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3572 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003573 err_code |= ERR_ALERT | ERR_FATAL;
3574 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003575 }
3576 hdr = calloc(sizeof(struct cap_hdr), 1);
3577 hdr->next = curproxy->rsp_cap;
3578 hdr->name = strdup(args[3]);
3579 hdr->namelen = strlen(args[3]);
3580 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003581 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003582 hdr->index = curproxy->nb_rsp_cap++;
3583 curproxy->rsp_cap = hdr;
3584 curproxy->to_log |= LW_RSPHDR;
3585 }
3586 else {
3587 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3588 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003589 err_code |= ERR_ALERT | ERR_FATAL;
3590 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003591 }
3592 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003593 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003594 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003595 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003596
William Lallemanddf1425a2015-04-28 20:17:49 +02003597 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3598 goto out;
3599
Willy Tarreaubaaee002006-06-26 02:48:02 +02003600 if (*(args[1]) == 0) {
3601 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003603 err_code |= ERR_ALERT | ERR_FATAL;
3604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003605 }
3606 curproxy->conn_retries = atol(args[1]);
3607 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003608 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003609 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003610
3611 if (curproxy == &defproxy) {
3612 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
3616
Willy Tarreau20b0de52012-12-24 15:45:22 +01003617 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3618 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3619 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3620 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003621 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003622 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3623 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 +01003624 file, linenum, args[0]);
3625 err_code |= ERR_WARN;
3626 }
3627
Willy Tarreauff011f22011-01-06 17:51:27 +01003628 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003629
Willy Tarreauff011f22011-01-06 17:51:27 +01003630 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003631 err_code |= ERR_ALERT | ERR_ABORT;
3632 goto out;
3633 }
3634
Willy Tarreau5002f572014-04-23 01:32:02 +02003635 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003636 err_code |= warnif_cond_conflicts(rule->cond,
3637 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3638 file, linenum);
3639
Willy Tarreauff011f22011-01-06 17:51:27 +01003640 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003641 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003642 else if (!strcmp(args[0], "http-response")) { /* response access control */
3643 struct http_res_rule *rule;
3644
3645 if (curproxy == &defproxy) {
3646 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3647 err_code |= ERR_ALERT | ERR_FATAL;
3648 goto out;
3649 }
3650
3651 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3652 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3653 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3654 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3655 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3656 file, linenum, args[0]);
3657 err_code |= ERR_WARN;
3658 }
3659
3660 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3661
3662 if (!rule) {
3663 err_code |= ERR_ALERT | ERR_ABORT;
3664 goto out;
3665 }
3666
3667 err_code |= warnif_cond_conflicts(rule->cond,
3668 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3669 file, linenum);
3670
3671 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3672 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003673 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3674 /* set the header name and length into the proxy structure */
3675 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3676 err_code |= ERR_WARN;
3677
3678 if (!*args[1]) {
3679 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3680 file, linenum, args[0]);
3681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
3683 }
3684
3685 /* set the desired header name */
3686 free(curproxy->server_id_hdr_name);
3687 curproxy->server_id_hdr_name = strdup(args[1]);
3688 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3689 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003690 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003691 struct http_req_rule *rule;
3692
Willy Tarreaub099aca2008-10-12 17:26:37 +02003693 if (curproxy == &defproxy) {
3694 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003697 }
3698
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003699 /* emulate "block" using "http-request block". Since these rules are supposed to
3700 * be processed before all http-request rules, we put them into their own list
3701 * and will insert them at the end.
3702 */
3703 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3704 if (!rule) {
3705 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003706 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003707 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003708 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3709 err_code |= warnif_cond_conflicts(rule->cond,
3710 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3711 file, linenum);
3712 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003713
3714 if (!already_warned(WARN_BLOCK_DEPRECATED))
3715 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]);
3716
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003717 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003718 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003719 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003720
Cyril Bonté99ed3272010-01-24 23:29:44 +01003721 if (curproxy == &defproxy) {
3722 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3723 err_code |= ERR_ALERT | ERR_FATAL;
3724 goto out;
3725 }
3726
Willy Tarreaube4653b2015-05-28 15:26:58 +02003727 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003728 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3729 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003730 err_code |= ERR_ALERT | ERR_FATAL;
3731 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003732 }
3733
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003734 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003735 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003736 err_code |= warnif_cond_conflicts(rule->cond,
3737 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3738 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003739 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003740 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003741 struct switching_rule *rule;
3742
Willy Tarreaub099aca2008-10-12 17:26:37 +02003743 if (curproxy == &defproxy) {
3744 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003747 }
3748
Willy Tarreau55ea7572007-06-17 19:56:27 +02003749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003750 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003751
3752 if (*(args[1]) == 0) {
3753 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003754 err_code |= ERR_ALERT | ERR_FATAL;
3755 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003756 }
3757
Willy Tarreauf51658d2014-04-23 01:21:56 +02003758 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3759 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3760 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3761 file, linenum, errmsg);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003765
Willy Tarreauf51658d2014-04-23 01:21:56 +02003766 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003767 }
3768
3769 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3770 rule->cond = cond;
3771 rule->be.name = strdup(args[1]);
3772 LIST_INIT(&rule->list);
3773 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3774 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003775 else if (strcmp(args[0], "use-server") == 0) {
3776 struct server_rule *rule;
3777
3778 if (curproxy == &defproxy) {
3779 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3780 err_code |= ERR_ALERT | ERR_FATAL;
3781 goto out;
3782 }
3783
3784 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3785 err_code |= ERR_WARN;
3786
3787 if (*(args[1]) == 0) {
3788 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3789 err_code |= ERR_ALERT | ERR_FATAL;
3790 goto out;
3791 }
3792
3793 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3794 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3795 file, linenum, args[0]);
3796 err_code |= ERR_ALERT | ERR_FATAL;
3797 goto out;
3798 }
3799
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003800 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3801 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3802 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003803 err_code |= ERR_ALERT | ERR_FATAL;
3804 goto out;
3805 }
3806
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003807 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003808
3809 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3810 rule->cond = cond;
3811 rule->srv.name = strdup(args[1]);
3812 LIST_INIT(&rule->list);
3813 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3814 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3815 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003816 else if ((!strcmp(args[0], "force-persist")) ||
3817 (!strcmp(args[0], "ignore-persist"))) {
3818 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003819
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_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3827 err_code |= ERR_WARN;
3828
Willy Tarreauef6494c2010-01-28 17:12:36 +01003829 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003830 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3831 file, linenum, args[0]);
3832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
3834 }
3835
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003836 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3837 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3838 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003839 err_code |= ERR_ALERT | ERR_FATAL;
3840 goto out;
3841 }
3842
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003843 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3844 * where force-persist is applied.
3845 */
3846 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003847
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003848 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003849 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003850 if (!strcmp(args[0], "force-persist")) {
3851 rule->type = PERSIST_TYPE_FORCE;
3852 } else {
3853 rule->type = PERSIST_TYPE_IGNORE;
3854 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003855 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003856 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003857 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003858 else if (!strcmp(args[0], "stick-table")) {
3859 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003860 struct proxy *other;
3861
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003862 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003863 if (other) {
3864 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3865 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3866 err_code |= ERR_ALERT | ERR_FATAL;
3867 goto out;
3868 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003869
Emeric Brun32da3c42010-09-23 18:39:19 +02003870 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003871 curproxy->table.type = (unsigned int)-1;
3872 while (*args[myidx]) {
3873 const char *err;
3874
3875 if (strcmp(args[myidx], "size") == 0) {
3876 myidx++;
3877 if (!*(args[myidx])) {
3878 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3879 file, linenum, args[myidx-1]);
3880 err_code |= ERR_ALERT | ERR_FATAL;
3881 goto out;
3882 }
3883 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3884 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3885 file, linenum, *err, args[myidx-1]);
3886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
3888 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003889 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003890 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003891 else if (strcmp(args[myidx], "peers") == 0) {
3892 myidx++;
Godbach50523162013-12-11 19:48:57 +08003893 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003894 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3895 file, linenum, args[myidx-1]);
3896 err_code |= ERR_ALERT | ERR_FATAL;
3897 goto out;
Godbach50523162013-12-11 19:48:57 +08003898 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003899 curproxy->table.peers.name = strdup(args[myidx++]);
3900 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003901 else if (strcmp(args[myidx], "expire") == 0) {
3902 myidx++;
3903 if (!*(args[myidx])) {
3904 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3905 file, linenum, args[myidx-1]);
3906 err_code |= ERR_ALERT | ERR_FATAL;
3907 goto out;
3908 }
3909 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3910 if (err) {
3911 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3912 file, linenum, *err, args[myidx-1]);
3913 err_code |= ERR_ALERT | ERR_FATAL;
3914 goto out;
3915 }
3916 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003917 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003918 }
3919 else if (strcmp(args[myidx], "nopurge") == 0) {
3920 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003921 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003922 }
3923 else if (strcmp(args[myidx], "type") == 0) {
3924 myidx++;
3925 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3926 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3927 file, linenum, args[myidx]);
3928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003931 /* myidx already points to next arg */
3932 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003933 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003934 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003935 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003936
3937 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003938 nw = args[myidx];
3939 while (*nw) {
3940 /* the "store" keyword supports a comma-separated list */
3941 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003942 sa = NULL; /* store arg */
3943 while (*nw && *nw != ',') {
3944 if (*nw == '(') {
3945 *nw = 0;
3946 sa = ++nw;
3947 while (*nw != ')') {
3948 if (!*nw) {
3949 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3950 file, linenum, args[0], cw);
3951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
3953 }
3954 nw++;
3955 }
3956 *nw = '\0';
3957 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003958 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003959 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003960 if (*nw)
3961 *nw++ = '\0';
3962 type = stktable_get_data_type(cw);
3963 if (type < 0) {
3964 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3965 file, linenum, args[0], cw);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
Willy Tarreauac782882010-06-20 10:41:54 +02003969
3970 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3971 switch (err) {
3972 case PE_NONE: break;
3973 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003974 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3975 file, linenum, args[0], cw);
3976 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003977 break;
3978
3979 case PE_ARG_MISSING:
3980 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3981 file, linenum, args[0], cw);
3982 err_code |= ERR_ALERT | ERR_FATAL;
3983 goto out;
3984
3985 case PE_ARG_NOT_USED:
3986 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3987 file, linenum, args[0], cw);
3988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
3990
3991 default:
3992 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3993 file, linenum, args[0], cw);
3994 err_code |= ERR_ALERT | ERR_FATAL;
3995 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003996 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003997 }
3998 myidx++;
3999 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004000 else {
4001 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4002 file, linenum, args[myidx]);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004005 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004006 }
4007
4008 if (!curproxy->table.size) {
4009 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4010 file, linenum);
4011 err_code |= ERR_ALERT | ERR_FATAL;
4012 goto out;
4013 }
4014
4015 if (curproxy->table.type == (unsigned int)-1) {
4016 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4017 file, linenum);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
4021 }
4022 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004023 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004024 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004025 int myidx = 0;
4026 const char *name = NULL;
4027 int flags;
4028
4029 if (curproxy == &defproxy) {
4030 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4031 err_code |= ERR_ALERT | ERR_FATAL;
4032 goto out;
4033 }
4034
4035 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4036 err_code |= ERR_WARN;
4037 goto out;
4038 }
4039
4040 myidx++;
4041 if ((strcmp(args[myidx], "store") == 0) ||
4042 (strcmp(args[myidx], "store-request") == 0)) {
4043 myidx++;
4044 flags = STK_IS_STORE;
4045 }
4046 else if (strcmp(args[myidx], "store-response") == 0) {
4047 myidx++;
4048 flags = STK_IS_STORE | STK_ON_RSP;
4049 }
4050 else if (strcmp(args[myidx], "match") == 0) {
4051 myidx++;
4052 flags = STK_IS_MATCH;
4053 }
4054 else if (strcmp(args[myidx], "on") == 0) {
4055 myidx++;
4056 flags = STK_IS_MATCH | STK_IS_STORE;
4057 }
4058 else {
4059 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4060 err_code |= ERR_ALERT | ERR_FATAL;
4061 goto out;
4062 }
4063
4064 if (*(args[myidx]) == 0) {
4065 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
4069
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004070 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004071 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004072 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004073 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004074 err_code |= ERR_ALERT | ERR_FATAL;
4075 goto out;
4076 }
4077
4078 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004079 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4080 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4081 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004082 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004083 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004084 goto out;
4085 }
4086 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004087 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4088 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4089 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004090 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004091 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004092 goto out;
4093 }
4094 }
4095
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004096 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004097 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004098
Emeric Brunb982a3d2010-01-04 15:45:53 +01004099 if (strcmp(args[myidx], "table") == 0) {
4100 myidx++;
4101 name = args[myidx++];
4102 }
4103
Willy Tarreauef6494c2010-01-28 17:12:36 +01004104 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004105 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4106 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4107 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004108 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004109 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004110 goto out;
4111 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004112 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004113 else if (*(args[myidx])) {
4114 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4115 file, linenum, args[0], args[myidx]);
4116 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004117 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004118 goto out;
4119 }
Emeric Brun97679e72010-09-23 17:56:44 +02004120 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004121 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004122 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004123 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004124
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4126 rule->cond = cond;
4127 rule->expr = expr;
4128 rule->flags = flags;
4129 rule->table.name = name ? strdup(name) : NULL;
4130 LIST_INIT(&rule->list);
4131 if (flags & STK_ON_RSP)
4132 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4133 else
4134 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4135 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004136 else if (!strcmp(args[0], "stats")) {
4137 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4138 curproxy->uri_auth = NULL; /* we must detach from the default config */
4139
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004140 if (!*args[1]) {
4141 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004142 } else if (!strcmp(args[1], "admin")) {
4143 struct stats_admin_rule *rule;
4144
4145 if (curproxy == &defproxy) {
4146 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4147 err_code |= ERR_ALERT | ERR_FATAL;
4148 goto out;
4149 }
4150
4151 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4152 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4153 err_code |= ERR_ALERT | ERR_ABORT;
4154 goto out;
4155 }
4156
4157 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4158 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4159 file, linenum, args[0], args[1]);
4160 err_code |= ERR_ALERT | ERR_FATAL;
4161 goto out;
4162 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004163 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4164 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4165 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004166 err_code |= ERR_ALERT | ERR_FATAL;
4167 goto out;
4168 }
4169
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004170 err_code |= warnif_cond_conflicts(cond,
4171 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4172 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004173
4174 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4175 rule->cond = cond;
4176 LIST_INIT(&rule->list);
4177 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004178 } else if (!strcmp(args[1], "uri")) {
4179 if (*(args[2]) == 0) {
4180 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004181 err_code |= ERR_ALERT | ERR_FATAL;
4182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004183 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4184 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004185 err_code |= ERR_ALERT | ERR_ABORT;
4186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004187 }
4188 } else if (!strcmp(args[1], "realm")) {
4189 if (*(args[2]) == 0) {
4190 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004193 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4194 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004195 err_code |= ERR_ALERT | ERR_ABORT;
4196 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004197 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004198 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004199 unsigned interval;
4200
4201 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4202 if (err) {
4203 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4204 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004205 err_code |= ERR_ALERT | ERR_FATAL;
4206 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004207 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4208 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004209 err_code |= ERR_ALERT | ERR_ABORT;
4210 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004211 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004212 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01004213 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004214
4215 if (curproxy == &defproxy) {
4216 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4217 err_code |= ERR_ALERT | ERR_FATAL;
4218 goto out;
4219 }
4220
4221 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4222 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4223 err_code |= ERR_ALERT | ERR_ABORT;
4224 goto out;
4225 }
4226
Willy Tarreauff011f22011-01-06 17:51:27 +01004227 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
4228 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004229 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4230 file, linenum, args[0]);
4231 err_code |= ERR_WARN;
4232 }
4233
Willy Tarreauff011f22011-01-06 17:51:27 +01004234 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004235
Willy Tarreauff011f22011-01-06 17:51:27 +01004236 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004237 err_code |= ERR_ALERT | ERR_ABORT;
4238 goto out;
4239 }
4240
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004241 err_code |= warnif_cond_conflicts(rule->cond,
4242 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4243 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004244 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004245
Willy Tarreaubaaee002006-06-26 02:48:02 +02004246 } else if (!strcmp(args[1], "auth")) {
4247 if (*(args[2]) == 0) {
4248 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004249 err_code |= ERR_ALERT | ERR_FATAL;
4250 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004251 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4252 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004253 err_code |= ERR_ALERT | ERR_ABORT;
4254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004255 }
4256 } else if (!strcmp(args[1], "scope")) {
4257 if (*(args[2]) == 0) {
4258 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004259 err_code |= ERR_ALERT | ERR_FATAL;
4260 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004261 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4262 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004263 err_code |= ERR_ALERT | ERR_ABORT;
4264 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004265 }
4266 } else if (!strcmp(args[1], "enable")) {
4267 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4268 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004269 err_code |= ERR_ALERT | ERR_ABORT;
4270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004271 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004272 } else if (!strcmp(args[1], "hide-version")) {
4273 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4274 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004275 err_code |= ERR_ALERT | ERR_ABORT;
4276 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004277 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004278 } else if (!strcmp(args[1], "show-legends")) {
4279 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4280 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4281 err_code |= ERR_ALERT | ERR_ABORT;
4282 goto out;
4283 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004284 } else if (!strcmp(args[1], "show-node")) {
4285
4286 if (*args[2]) {
4287 int i;
4288 char c;
4289
4290 for (i=0; args[2][i]; i++) {
4291 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004292 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4293 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004294 break;
4295 }
4296
4297 if (!i || args[2][i]) {
4298 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4299 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4300 file, linenum, args[0], args[1]);
4301 err_code |= ERR_ALERT | ERR_FATAL;
4302 goto out;
4303 }
4304 }
4305
4306 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4307 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4308 err_code |= ERR_ALERT | ERR_ABORT;
4309 goto out;
4310 }
4311 } else if (!strcmp(args[1], "show-desc")) {
4312 char *desc = NULL;
4313
4314 if (*args[2]) {
4315 int i, len=0;
4316 char *d;
4317
Willy Tarreau348acfe2014-04-14 15:00:39 +02004318 for (i = 2; *args[i]; i++)
4319 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004320
4321 desc = d = (char *)calloc(1, len);
4322
Willy Tarreau348acfe2014-04-14 15:00:39 +02004323 d += snprintf(d, desc + len - d, "%s", args[2]);
4324 for (i = 3; *args[i]; i++)
4325 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004326 }
4327
4328 if (!*args[2] && !global.desc)
4329 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4330 file, linenum, args[1]);
4331 else {
4332 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4333 free(desc);
4334 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4335 err_code |= ERR_ALERT | ERR_ABORT;
4336 goto out;
4337 }
4338 free(desc);
4339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004340 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004341stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004342 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 +01004343 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004344 err_code |= ERR_ALERT | ERR_FATAL;
4345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004346 }
4347 }
4348 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004349 int optnum;
4350
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004351 if (*(args[1]) == '\0') {
4352 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004354 err_code |= ERR_ALERT | ERR_FATAL;
4355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004356 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004357
4358 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4359 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004360 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4361 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4362 file, linenum, cfg_opts[optnum].name);
4363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
4365 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004366 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4367 goto out;
4368
Willy Tarreau93893792009-07-23 13:19:11 +02004369 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4370 err_code |= ERR_WARN;
4371 goto out;
4372 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004373
Willy Tarreau3842f002009-06-14 11:39:52 +02004374 curproxy->no_options &= ~cfg_opts[optnum].val;
4375 curproxy->options &= ~cfg_opts[optnum].val;
4376
4377 switch (kwm) {
4378 case KWM_STD:
4379 curproxy->options |= cfg_opts[optnum].val;
4380 break;
4381 case KWM_NO:
4382 curproxy->no_options |= cfg_opts[optnum].val;
4383 break;
4384 case KWM_DEF: /* already cleared */
4385 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004386 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004387
Willy Tarreau93893792009-07-23 13:19:11 +02004388 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004389 }
4390 }
4391
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004392 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4393 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004394 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4395 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4396 file, linenum, cfg_opts2[optnum].name);
4397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
4399 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004400 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4401 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004402 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4403 err_code |= ERR_WARN;
4404 goto out;
4405 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004406
Willy Tarreau3842f002009-06-14 11:39:52 +02004407 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4408 curproxy->options2 &= ~cfg_opts2[optnum].val;
4409
4410 switch (kwm) {
4411 case KWM_STD:
4412 curproxy->options2 |= cfg_opts2[optnum].val;
4413 break;
4414 case KWM_NO:
4415 curproxy->no_options2 |= cfg_opts2[optnum].val;
4416 break;
4417 case KWM_DEF: /* already cleared */
4418 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004419 }
Willy Tarreau93893792009-07-23 13:19:11 +02004420 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004421 }
4422 }
4423
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004424 /* HTTP options override each other. They can be cancelled using
4425 * "no option xxx" which only switches to default mode if the mode
4426 * was this one (useful for cancelling options set in defaults
4427 * sections).
4428 */
4429 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004430 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4431 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004432 if (kwm == KWM_STD) {
4433 curproxy->options &= ~PR_O_HTTP_MODE;
4434 curproxy->options |= PR_O_HTTP_PCL;
4435 goto out;
4436 }
4437 else if (kwm == KWM_NO) {
4438 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4439 curproxy->options &= ~PR_O_HTTP_MODE;
4440 goto out;
4441 }
4442 }
4443 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004444 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4445 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004446 if (kwm == KWM_STD) {
4447 curproxy->options &= ~PR_O_HTTP_MODE;
4448 curproxy->options |= PR_O_HTTP_FCL;
4449 goto out;
4450 }
4451 else if (kwm == KWM_NO) {
4452 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4453 curproxy->options &= ~PR_O_HTTP_MODE;
4454 goto out;
4455 }
4456 }
4457 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004458 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4459 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004460 if (kwm == KWM_STD) {
4461 curproxy->options &= ~PR_O_HTTP_MODE;
4462 curproxy->options |= PR_O_HTTP_SCL;
4463 goto out;
4464 }
4465 else if (kwm == KWM_NO) {
4466 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4467 curproxy->options &= ~PR_O_HTTP_MODE;
4468 goto out;
4469 }
4470 }
4471 else if (strcmp(args[1], "http-keep-alive") == 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_KAL;
4477 goto out;
4478 }
4479 else if (kwm == KWM_NO) {
4480 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4481 curproxy->options &= ~PR_O_HTTP_MODE;
4482 goto out;
4483 }
4484 }
4485 else if (strcmp(args[1], "http-tunnel") == 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_TUN;
4491 goto out;
4492 }
4493 else if (kwm == KWM_NO) {
4494 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4495 curproxy->options &= ~PR_O_HTTP_MODE;
4496 goto out;
4497 }
4498 }
4499
Joseph Lynch726ab712015-05-11 23:25:34 -07004500 /* Redispatch can take an integer argument that control when the
4501 * resispatch occurs. All values are relative to the retries option.
4502 * This can be cancelled using "no option xxx".
4503 */
4504 if (strcmp(args[1], "redispatch") == 0) {
4505 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4506 err_code |= ERR_WARN;
4507 goto out;
4508 }
4509
4510 curproxy->no_options &= ~PR_O_REDISP;
4511 curproxy->options &= ~PR_O_REDISP;
4512
4513 switch (kwm) {
4514 case KWM_STD:
4515 curproxy->options |= PR_O_REDISP;
4516 curproxy->redispatch_after = -1;
4517 if(*args[2]) {
4518 curproxy->redispatch_after = atol(args[2]);
4519 }
4520 break;
4521 case KWM_NO:
4522 curproxy->no_options |= PR_O_REDISP;
4523 curproxy->redispatch_after = 0;
4524 break;
4525 case KWM_DEF: /* already cleared */
4526 break;
4527 }
4528 goto out;
4529 }
4530
Willy Tarreau3842f002009-06-14 11:39:52 +02004531 if (kwm != KWM_STD) {
4532 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004533 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004534 err_code |= ERR_ALERT | ERR_FATAL;
4535 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004536 }
4537
Emeric Brun3a058f32009-06-30 18:26:00 +02004538 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004539 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004540 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004541 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004542 if (*(args[2]) != '\0') {
4543 if (!strcmp(args[2], "clf")) {
4544 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004545 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004546 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004547 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004548 err_code |= ERR_ALERT | ERR_FATAL;
4549 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004550 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004551 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4552 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004553 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004554 if (curproxy->conf.logformat_string != default_http_log_format &&
4555 curproxy->conf.logformat_string != default_tcp_log_format &&
4556 curproxy->conf.logformat_string != clf_http_log_format)
4557 free(curproxy->conf.logformat_string);
4558 curproxy->conf.logformat_string = logformat;
4559
4560 free(curproxy->conf.lfs_file);
4561 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4562 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004563 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004564 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004565 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004566 if (curproxy->conf.logformat_string != default_http_log_format &&
4567 curproxy->conf.logformat_string != default_tcp_log_format &&
4568 curproxy->conf.logformat_string != clf_http_log_format)
4569 free(curproxy->conf.logformat_string);
4570 curproxy->conf.logformat_string = default_tcp_log_format;
4571
4572 free(curproxy->conf.lfs_file);
4573 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4574 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004575
4576 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4577 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004578 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004579 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004580 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004581 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004582 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004583
William Lallemanddf1425a2015-04-28 20:17:49 +02004584 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4585 goto out;
4586
Willy Tarreau13943ab2006-12-31 00:24:10 +01004587 if (curproxy->cap & PR_CAP_FE)
4588 curproxy->options |= PR_O_TCP_CLI_KA;
4589 if (curproxy->cap & PR_CAP_BE)
4590 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004591 }
4592 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004593 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004594 err_code |= ERR_WARN;
4595
Willy Tarreaubaaee002006-06-26 02:48:02 +02004596 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004597 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004598 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004599 curproxy->options2 &= ~PR_O2_CHK_ANY;
4600 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004601 if (!*args[2]) { /* no argument */
4602 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4603 curproxy->check_len = strlen(DEF_CHECK_REQ);
4604 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004605 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004606 curproxy->check_req = (char *)malloc(reqlen);
4607 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004608 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004609 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004610 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004611 if (*args[4])
4612 reqlen += strlen(args[4]);
4613 else
4614 reqlen += strlen("HTTP/1.0");
4615
4616 curproxy->check_req = (char *)malloc(reqlen);
4617 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004618 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004619 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004620 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4621 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004622 }
4623 else if (!strcmp(args[1], "ssl-hello-chk")) {
4624 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004625 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004626 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004627
Willy Tarreaua534fea2008-08-03 12:19:50 +02004628 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004629 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004630 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004631 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004632
4633 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004635 }
Willy Tarreau23677902007-05-08 23:50:35 +02004636 else if (!strcmp(args[1], "smtpchk")) {
4637 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004638 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004639 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004640 curproxy->options2 &= ~PR_O2_CHK_ANY;
4641 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004642
4643 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4644 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4645 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4646 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4647 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4648 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4649 curproxy->check_req = (char *)malloc(reqlen);
4650 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4651 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4652 } else {
4653 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4654 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4655 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4656 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4657 }
4658 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004659 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4660 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004661 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004662 else if (!strcmp(args[1], "pgsql-check")) {
4663 /* use PostgreSQL request to check servers' health */
4664 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4665 err_code |= ERR_WARN;
4666
4667 free(curproxy->check_req);
4668 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004669 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004670 curproxy->options2 |= PR_O2_PGSQL_CHK;
4671
4672 if (*(args[2])) {
4673 int cur_arg = 2;
4674
4675 while (*(args[cur_arg])) {
4676 if (strcmp(args[cur_arg], "user") == 0) {
4677 char * packet;
4678 uint32_t packet_len;
4679 uint32_t pv;
4680
4681 /* suboption header - needs additional argument for it */
4682 if (*(args[cur_arg+1]) == 0) {
4683 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4684 file, linenum, args[0], args[1], args[cur_arg]);
4685 err_code |= ERR_ALERT | ERR_FATAL;
4686 goto out;
4687 }
4688
4689 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4690 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4691 pv = htonl(0x30000); /* protocol version 3.0 */
4692
4693 packet = (char*) calloc(1, packet_len);
4694
4695 memcpy(packet + 4, &pv, 4);
4696
4697 /* copy "user" */
4698 memcpy(packet + 8, "user", 4);
4699
4700 /* copy username */
4701 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4702
4703 free(curproxy->check_req);
4704 curproxy->check_req = packet;
4705 curproxy->check_len = packet_len;
4706
4707 packet_len = htonl(packet_len);
4708 memcpy(packet, &packet_len, 4);
4709 cur_arg += 2;
4710 } else {
4711 /* unknown suboption - catchall */
4712 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4713 file, linenum, args[0], args[1]);
4714 err_code |= ERR_ALERT | ERR_FATAL;
4715 goto out;
4716 }
4717 } /* end while loop */
4718 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004719 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4720 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004721 }
4722
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004723 else if (!strcmp(args[1], "redis-check")) {
4724 /* use REDIS PING request to check servers' health */
4725 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4726 err_code |= ERR_WARN;
4727
4728 free(curproxy->check_req);
4729 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004730 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004731 curproxy->options2 |= PR_O2_REDIS_CHK;
4732
4733 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4734 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4735 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004736
4737 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4738 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004739 }
4740
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004741 else if (!strcmp(args[1], "mysql-check")) {
4742 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004743 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4744 err_code |= ERR_WARN;
4745
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004746 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004747 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004748 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004749 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004750
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004751 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004752 * const char mysql40_client_auth_pkt[] = {
4753 * "\x0e\x00\x00" // packet length
4754 * "\x01" // packet number
4755 * "\x00\x00" // client capabilities
4756 * "\x00\x00\x01" // max packet
4757 * "haproxy\x00" // username (null terminated string)
4758 * "\x00" // filler (always 0x00)
4759 * "\x01\x00\x00" // packet length
4760 * "\x00" // packet number
4761 * "\x01" // COM_QUIT command
4762 * };
4763 */
4764
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004765 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4766 * const char mysql41_client_auth_pkt[] = {
4767 * "\x0e\x00\x00\" // packet length
4768 * "\x01" // packet number
4769 * "\x00\x00\x00\x00" // client capabilities
4770 * "\x00\x00\x00\x01" // max packet
4771 * "\x21" // character set (UTF-8)
4772 * char[23] // All zeroes
4773 * "haproxy\x00" // username (null terminated string)
4774 * "\x00" // filler (always 0x00)
4775 * "\x01\x00\x00" // packet length
4776 * "\x00" // packet number
4777 * "\x01" // COM_QUIT command
4778 * };
4779 */
4780
4781
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004782 if (*(args[2])) {
4783 int cur_arg = 2;
4784
4785 while (*(args[cur_arg])) {
4786 if (strcmp(args[cur_arg], "user") == 0) {
4787 char *mysqluser;
4788 int packetlen, reqlen, userlen;
4789
4790 /* suboption header - needs additional argument for it */
4791 if (*(args[cur_arg+1]) == 0) {
4792 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4793 file, linenum, args[0], args[1], args[cur_arg]);
4794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
4796 }
4797 mysqluser = args[cur_arg + 1];
4798 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004799
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004800 if (*(args[cur_arg+2])) {
4801 if (!strcmp(args[cur_arg+2], "post-41")) {
4802 packetlen = userlen + 7 + 27;
4803 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004804
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004805 free(curproxy->check_req);
4806 curproxy->check_req = (char *)calloc(1, reqlen);
4807 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004808
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004809 snprintf(curproxy->check_req, 4, "%c%c%c",
4810 ((unsigned char) packetlen & 0xff),
4811 ((unsigned char) (packetlen >> 8) & 0xff),
4812 ((unsigned char) (packetlen >> 16) & 0xff));
4813
4814 curproxy->check_req[3] = 1;
4815 curproxy->check_req[5] = 130;
4816 curproxy->check_req[11] = 1;
4817 curproxy->check_req[12] = 33;
4818 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4819 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4820 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4821 cur_arg += 3;
4822 } else {
4823 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4824 err_code |= ERR_ALERT | ERR_FATAL;
4825 goto out;
4826 }
4827 } else {
4828 packetlen = userlen + 7;
4829 reqlen = packetlen + 9;
4830
4831 free(curproxy->check_req);
4832 curproxy->check_req = (char *)calloc(1, reqlen);
4833 curproxy->check_len = reqlen;
4834
4835 snprintf(curproxy->check_req, 4, "%c%c%c",
4836 ((unsigned char) packetlen & 0xff),
4837 ((unsigned char) (packetlen >> 8) & 0xff),
4838 ((unsigned char) (packetlen >> 16) & 0xff));
4839
4840 curproxy->check_req[3] = 1;
4841 curproxy->check_req[5] = 128;
4842 curproxy->check_req[8] = 1;
4843 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4844 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4845 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4846 cur_arg += 2;
4847 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004848 } else {
4849 /* unknown suboption - catchall */
4850 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4851 file, linenum, args[0], args[1]);
4852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
4854 }
4855 } /* end while loop */
4856 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004857 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004858 else if (!strcmp(args[1], "ldap-check")) {
4859 /* use LDAP request to check servers' health */
4860 free(curproxy->check_req);
4861 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004862 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004863 curproxy->options2 |= PR_O2_LDAP_CHK;
4864
4865 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4866 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4867 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004868 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4869 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004870 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004871 else if (!strcmp(args[1], "tcp-check")) {
4872 /* use raw TCPCHK send/expect to check servers' health */
4873 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4874 err_code |= ERR_WARN;
4875
4876 free(curproxy->check_req);
4877 curproxy->check_req = NULL;
4878 curproxy->options2 &= ~PR_O2_CHK_ANY;
4879 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004880 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4881 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004882 }
Simon Horman98637e52014-06-20 12:30:16 +09004883 else if (!strcmp(args[1], "external-check")) {
4884 /* excute an external command to check servers' health */
4885 free(curproxy->check_req);
4886 curproxy->check_req = NULL;
4887 curproxy->options2 &= ~PR_O2_CHK_ANY;
4888 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004889 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4890 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004891 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004892 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004893 int cur_arg;
4894
4895 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4896 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004897 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004898
Willy Tarreau87cf5142011-08-19 22:57:24 +02004899 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004900
4901 free(curproxy->fwdfor_hdr_name);
4902 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4903 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4904
4905 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4906 cur_arg = 2;
4907 while (*(args[cur_arg])) {
4908 if (!strcmp(args[cur_arg], "except")) {
4909 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004910 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004911 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4912 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004913 err_code |= ERR_ALERT | ERR_FATAL;
4914 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004915 }
4916 /* flush useless bits */
4917 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004918 cur_arg += 2;
4919 } else if (!strcmp(args[cur_arg], "header")) {
4920 /* suboption header - needs additional argument for it */
4921 if (*(args[cur_arg+1]) == 0) {
4922 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4923 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004924 err_code |= ERR_ALERT | ERR_FATAL;
4925 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004926 }
4927 free(curproxy->fwdfor_hdr_name);
4928 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4929 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4930 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004931 } else if (!strcmp(args[cur_arg], "if-none")) {
4932 curproxy->options &= ~PR_O_FF_ALWAYS;
4933 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004934 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004935 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004936 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004937 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004940 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004941 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004942 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004943 else if (!strcmp(args[1], "originalto")) {
4944 int cur_arg;
4945
4946 /* insert x-original-to field, but not for the IP address listed as an except.
4947 * set default options (ie: bitfield, header name, etc)
4948 */
4949
4950 curproxy->options |= PR_O_ORGTO;
4951
4952 free(curproxy->orgto_hdr_name);
4953 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4954 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4955
Willy Tarreau87cf5142011-08-19 22:57:24 +02004956 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004957 cur_arg = 2;
4958 while (*(args[cur_arg])) {
4959 if (!strcmp(args[cur_arg], "except")) {
4960 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004961 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 +02004962 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4963 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004964 err_code |= ERR_ALERT | ERR_FATAL;
4965 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004966 }
4967 /* flush useless bits */
4968 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4969 cur_arg += 2;
4970 } else if (!strcmp(args[cur_arg], "header")) {
4971 /* suboption header - needs additional argument for it */
4972 if (*(args[cur_arg+1]) == 0) {
4973 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4974 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004975 err_code |= ERR_ALERT | ERR_FATAL;
4976 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004977 }
4978 free(curproxy->orgto_hdr_name);
4979 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4980 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4981 cur_arg += 2;
4982 } else {
4983 /* unknown suboption - catchall */
4984 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4985 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004986 err_code |= ERR_ALERT | ERR_FATAL;
4987 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004988 }
4989 } /* end while loop */
4990 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004991 else {
4992 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004993 err_code |= ERR_ALERT | ERR_FATAL;
4994 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004995 }
Willy Tarreau93893792009-07-23 13:19:11 +02004996 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004997 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004998 else if (!strcmp(args[0], "default_backend")) {
4999 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005000 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005001
5002 if (*(args[1]) == 0) {
5003 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005006 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005007 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005008 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005009
5010 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5011 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005012 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005013 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005014 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005015 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005016
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005017 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5018 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 +01005019 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005020 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005021 /* enable reconnections to dispatch */
5022 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005023
5024 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5025 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005026 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005027 else if (!strcmp(args[0], "http-reuse")) {
5028 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5029 err_code |= ERR_WARN;
5030
5031 if (strcmp(args[1], "never") == 0) {
5032 /* enable a graceful server shutdown on an HTTP 404 response */
5033 curproxy->options &= ~PR_O_REUSE_MASK;
5034 curproxy->options |= PR_O_REUSE_NEVR;
5035 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5036 goto out;
5037 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005038 else if (strcmp(args[1], "safe") == 0) {
5039 /* enable a graceful server shutdown on an HTTP 404 response */
5040 curproxy->options &= ~PR_O_REUSE_MASK;
5041 curproxy->options |= PR_O_REUSE_SAFE;
5042 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5043 goto out;
5044 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005045 else if (strcmp(args[1], "aggressive") == 0) {
5046 curproxy->options &= ~PR_O_REUSE_MASK;
5047 curproxy->options |= PR_O_REUSE_AGGR;
5048 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5049 goto out;
5050 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005051 else if (strcmp(args[1], "always") == 0) {
5052 /* enable a graceful server shutdown on an HTTP 404 response */
5053 curproxy->options &= ~PR_O_REUSE_MASK;
5054 curproxy->options |= PR_O_REUSE_ALWS;
5055 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5056 goto out;
5057 }
5058 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005059 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005060 err_code |= ERR_ALERT | ERR_FATAL;
5061 goto out;
5062 }
5063 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005064 else if (!strcmp(args[0], "http-check")) {
5065 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005066 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005067
5068 if (strcmp(args[1], "disable-on-404") == 0) {
5069 /* enable a graceful server shutdown on an HTTP 404 response */
5070 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005071 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5072 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005073 }
Willy Tarreauef781042010-01-27 11:53:01 +01005074 else if (strcmp(args[1], "send-state") == 0) {
5075 /* enable emission of the apparent state of a server in HTTP checks */
5076 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005077 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5078 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005079 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005080 else if (strcmp(args[1], "expect") == 0) {
5081 const char *ptr_arg;
5082 int cur_arg;
5083
5084 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5085 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5086 err_code |= ERR_ALERT | ERR_FATAL;
5087 goto out;
5088 }
5089
5090 cur_arg = 2;
5091 /* consider exclamation marks, sole or at the beginning of a word */
5092 while (*(ptr_arg = args[cur_arg])) {
5093 while (*ptr_arg == '!') {
5094 curproxy->options2 ^= PR_O2_EXP_INV;
5095 ptr_arg++;
5096 }
5097 if (*ptr_arg)
5098 break;
5099 cur_arg++;
5100 }
5101 /* now ptr_arg points to the beginning of a word past any possible
5102 * exclamation mark, and cur_arg is the argument which holds this word.
5103 */
5104 if (strcmp(ptr_arg, "status") == 0) {
5105 if (!*(args[cur_arg + 1])) {
5106 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5107 file, linenum, args[0], args[1], ptr_arg);
5108 err_code |= ERR_ALERT | ERR_FATAL;
5109 goto out;
5110 }
5111 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005112 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005113 curproxy->expect_str = strdup(args[cur_arg + 1]);
5114 }
5115 else if (strcmp(ptr_arg, "string") == 0) {
5116 if (!*(args[cur_arg + 1])) {
5117 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5118 file, linenum, args[0], args[1], ptr_arg);
5119 err_code |= ERR_ALERT | ERR_FATAL;
5120 goto out;
5121 }
5122 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005123 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005124 curproxy->expect_str = strdup(args[cur_arg + 1]);
5125 }
5126 else if (strcmp(ptr_arg, "rstatus") == 0) {
5127 if (!*(args[cur_arg + 1])) {
5128 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5129 file, linenum, args[0], args[1], ptr_arg);
5130 err_code |= ERR_ALERT | ERR_FATAL;
5131 goto out;
5132 }
5133 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005134 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005135 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005136 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005137 free(curproxy->expect_regex);
5138 curproxy->expect_regex = NULL;
5139 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005140 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005141 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5142 error = NULL;
5143 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5144 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5145 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5146 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005147 err_code |= ERR_ALERT | ERR_FATAL;
5148 goto out;
5149 }
5150 }
5151 else if (strcmp(ptr_arg, "rstring") == 0) {
5152 if (!*(args[cur_arg + 1])) {
5153 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5154 file, linenum, args[0], args[1], ptr_arg);
5155 err_code |= ERR_ALERT | ERR_FATAL;
5156 goto out;
5157 }
5158 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005159 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005160 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005161 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005162 free(curproxy->expect_regex);
5163 curproxy->expect_regex = NULL;
5164 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005165 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005166 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5167 error = NULL;
5168 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5169 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5170 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5171 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005172 err_code |= ERR_ALERT | ERR_FATAL;
5173 goto out;
5174 }
5175 }
5176 else {
5177 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5178 file, linenum, args[0], args[1], ptr_arg);
5179 err_code |= ERR_ALERT | ERR_FATAL;
5180 goto out;
5181 }
5182 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005183 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005184 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 +02005185 err_code |= ERR_ALERT | ERR_FATAL;
5186 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005187 }
5188 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005189 else if (!strcmp(args[0], "tcp-check")) {
5190 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5191 err_code |= ERR_WARN;
5192
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005193 if (strcmp(args[1], "comment") == 0) {
5194 int cur_arg;
5195 struct tcpcheck_rule *tcpcheck;
5196
5197 cur_arg = 1;
5198 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5199 tcpcheck->action = TCPCHK_ACT_COMMENT;
5200
5201 if (!*args[cur_arg + 1]) {
5202 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5203 file, linenum, args[cur_arg]);
5204 err_code |= ERR_ALERT | ERR_FATAL;
5205 goto out;
5206 }
5207
5208 tcpcheck->comment = strdup(args[cur_arg + 1]);
5209
5210 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005211 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5212 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005213 }
5214 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005215 const char *ptr_arg;
5216 int cur_arg;
5217 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005218
5219 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005220 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5221 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5222 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5223 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5224 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005225
Willy Tarreau5581c272015-05-13 12:24:53 +02005226 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5227 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5228 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5229 file, linenum);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005232 }
5233
5234 cur_arg = 2;
5235 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5236 tcpcheck->action = TCPCHK_ACT_CONNECT;
5237
5238 /* parsing each parameters to fill up the rule */
5239 while (*(ptr_arg = args[cur_arg])) {
5240 /* tcp port */
5241 if (strcmp(args[cur_arg], "port") == 0) {
5242 if ( (atol(args[cur_arg + 1]) > 65535) ||
5243 (atol(args[cur_arg + 1]) < 1) ){
5244 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5245 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249 tcpcheck->port = atol(args[cur_arg + 1]);
5250 cur_arg += 2;
5251 }
5252 /* send proxy protocol */
5253 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5254 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5255 cur_arg++;
5256 }
5257#ifdef USE_OPENSSL
5258 else if (strcmp(args[cur_arg], "ssl") == 0) {
5259 curproxy->options |= PR_O_TCPCHK_SSL;
5260 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5261 cur_arg++;
5262 }
5263#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005264 /* comment for this tcpcheck line */
5265 else if (strcmp(args[cur_arg], "comment") == 0) {
5266 if (!*args[cur_arg + 1]) {
5267 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5268 file, linenum, args[cur_arg]);
5269 err_code |= ERR_ALERT | ERR_FATAL;
5270 goto out;
5271 }
5272 tcpcheck->comment = strdup(args[cur_arg + 1]);
5273 cur_arg += 2;
5274 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005275 else {
5276#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005277 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 +01005278#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005279 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 +01005280#endif /* USE_OPENSSL */
5281 file, linenum, args[0], args[1], args[cur_arg]);
5282 err_code |= ERR_ALERT | ERR_FATAL;
5283 goto out;
5284 }
5285
5286 }
5287
5288 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5289 }
5290 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005291 if (! *(args[2]) ) {
5292 /* SEND string expected */
5293 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5294 file, linenum, args[0], args[1], args[2]);
5295 err_code |= ERR_ALERT | ERR_FATAL;
5296 goto out;
5297 } else {
5298 struct tcpcheck_rule *tcpcheck;
5299
5300 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5301
5302 tcpcheck->action = TCPCHK_ACT_SEND;
5303 tcpcheck->string_len = strlen(args[2]);
5304 tcpcheck->string = strdup(args[2]);
5305 tcpcheck->expect_regex = NULL;
5306
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005307 /* comment for this tcpcheck line */
5308 if (strcmp(args[3], "comment") == 0) {
5309 if (!*args[4]) {
5310 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5311 file, linenum, args[3]);
5312 err_code |= ERR_ALERT | ERR_FATAL;
5313 goto out;
5314 }
5315 tcpcheck->comment = strdup(args[4]);
5316 }
5317
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005318 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5319 }
5320 }
5321 else if (strcmp(args[1], "send-binary") == 0) {
5322 if (! *(args[2]) ) {
5323 /* SEND binary string expected */
5324 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5325 file, linenum, args[0], args[1], args[2]);
5326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
5328 } else {
5329 struct tcpcheck_rule *tcpcheck;
5330 char *err = NULL;
5331
5332 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5333
5334 tcpcheck->action = TCPCHK_ACT_SEND;
5335 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5336 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5337 file, linenum, args[0], args[1], args[2], err);
5338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
5340 }
5341 tcpcheck->expect_regex = NULL;
5342
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005343 /* comment for this tcpcheck line */
5344 if (strcmp(args[3], "comment") == 0) {
5345 if (!*args[4]) {
5346 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5347 file, linenum, args[3]);
5348 err_code |= ERR_ALERT | ERR_FATAL;
5349 goto out;
5350 }
5351 tcpcheck->comment = strdup(args[4]);
5352 }
5353
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005354 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5355 }
5356 }
5357 else if (strcmp(args[1], "expect") == 0) {
5358 const char *ptr_arg;
5359 int cur_arg;
5360 int inverse = 0;
5361
5362 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5363 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5364 err_code |= ERR_ALERT | ERR_FATAL;
5365 goto out;
5366 }
5367
5368 cur_arg = 2;
5369 /* consider exclamation marks, sole or at the beginning of a word */
5370 while (*(ptr_arg = args[cur_arg])) {
5371 while (*ptr_arg == '!') {
5372 inverse = !inverse;
5373 ptr_arg++;
5374 }
5375 if (*ptr_arg)
5376 break;
5377 cur_arg++;
5378 }
5379 /* now ptr_arg points to the beginning of a word past any possible
5380 * exclamation mark, and cur_arg is the argument which holds this word.
5381 */
5382 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005383 struct tcpcheck_rule *tcpcheck;
5384 char *err = NULL;
5385
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005386 if (!*(args[cur_arg + 1])) {
5387 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5388 file, linenum, args[0], args[1], ptr_arg);
5389 err_code |= ERR_ALERT | ERR_FATAL;
5390 goto out;
5391 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005392
5393 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5394
5395 tcpcheck->action = TCPCHK_ACT_EXPECT;
5396 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5397 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5398 file, linenum, args[0], args[1], args[2], err);
5399 err_code |= ERR_ALERT | ERR_FATAL;
5400 goto out;
5401 }
5402 tcpcheck->expect_regex = NULL;
5403 tcpcheck->inverse = inverse;
5404
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005405 /* tcpcheck comment */
5406 cur_arg += 2;
5407 if (strcmp(args[cur_arg], "comment") == 0) {
5408 if (!*args[cur_arg + 1]) {
5409 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5410 file, linenum, args[cur_arg + 1]);
5411 err_code |= ERR_ALERT | ERR_FATAL;
5412 goto out;
5413 }
5414 tcpcheck->comment = strdup(args[cur_arg + 1]);
5415 }
5416
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005417 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5418 }
5419 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005420 struct tcpcheck_rule *tcpcheck;
5421
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005422 if (!*(args[cur_arg + 1])) {
5423 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5424 file, linenum, args[0], args[1], ptr_arg);
5425 err_code |= ERR_ALERT | ERR_FATAL;
5426 goto out;
5427 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005428
5429 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5430
5431 tcpcheck->action = TCPCHK_ACT_EXPECT;
5432 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5433 tcpcheck->string = strdup(args[cur_arg + 1]);
5434 tcpcheck->expect_regex = NULL;
5435 tcpcheck->inverse = inverse;
5436
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005437 /* tcpcheck comment */
5438 cur_arg += 2;
5439 if (strcmp(args[cur_arg], "comment") == 0) {
5440 if (!*args[cur_arg + 1]) {
5441 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5442 file, linenum, args[cur_arg + 1]);
5443 err_code |= ERR_ALERT | ERR_FATAL;
5444 goto out;
5445 }
5446 tcpcheck->comment = strdup(args[cur_arg + 1]);
5447 }
5448
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005449 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5450 }
5451 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005452 struct tcpcheck_rule *tcpcheck;
5453
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005454 if (!*(args[cur_arg + 1])) {
5455 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5456 file, linenum, args[0], args[1], ptr_arg);
5457 err_code |= ERR_ALERT | ERR_FATAL;
5458 goto out;
5459 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005460
5461 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5462
5463 tcpcheck->action = TCPCHK_ACT_EXPECT;
5464 tcpcheck->string_len = 0;
5465 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005466 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5467 error = NULL;
5468 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5469 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5470 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5471 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
5475 tcpcheck->inverse = inverse;
5476
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005477 /* tcpcheck comment */
5478 cur_arg += 2;
5479 if (strcmp(args[cur_arg], "comment") == 0) {
5480 if (!*args[cur_arg + 1]) {
5481 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5482 file, linenum, args[cur_arg + 1]);
5483 err_code |= ERR_ALERT | ERR_FATAL;
5484 goto out;
5485 }
5486 tcpcheck->comment = strdup(args[cur_arg + 1]);
5487 }
5488
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005489 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5490 }
5491 else {
5492 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5493 file, linenum, args[0], args[1], ptr_arg);
5494 err_code |= ERR_ALERT | ERR_FATAL;
5495 goto out;
5496 }
5497 }
5498 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005499 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005500 err_code |= ERR_ALERT | ERR_FATAL;
5501 goto out;
5502 }
5503 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005504 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005505 if (curproxy == &defproxy) {
5506 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005507 err_code |= ERR_ALERT | ERR_FATAL;
5508 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005509 }
5510
Willy Tarreaub80c2302007-11-30 20:51:32 +01005511 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005512 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005513
5514 if (strcmp(args[1], "fail") == 0) {
5515 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005516 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005517 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5518 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005519 err_code |= ERR_ALERT | ERR_FATAL;
5520 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005521 }
5522
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005523 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5524 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5525 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005526 err_code |= ERR_ALERT | ERR_FATAL;
5527 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005528 }
5529 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5530 }
5531 else {
5532 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005533 err_code |= ERR_ALERT | ERR_FATAL;
5534 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005535 }
5536 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005537#ifdef TPROXY
5538 else if (!strcmp(args[0], "transparent")) {
5539 /* enable transparent proxy connections */
5540 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005541 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005543 }
5544#endif
5545 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005546 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005547 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005548
Willy Tarreaubaaee002006-06-26 02:48:02 +02005549 if (*(args[1]) == 0) {
5550 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005553 }
5554 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005555 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5556 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005557 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005558 else if (!strcmp(args[0], "backlog")) { /* backlog */
5559 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005560 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005561
5562 if (*(args[1]) == 0) {
5563 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005564 err_code |= ERR_ALERT | ERR_FATAL;
5565 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005566 }
5567 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005568 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5569 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005570 }
Willy Tarreau86034312006-12-29 00:10:33 +01005571 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005572 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005573 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005574
Willy Tarreau86034312006-12-29 00:10:33 +01005575 if (*(args[1]) == 0) {
5576 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005577 err_code |= ERR_ALERT | ERR_FATAL;
5578 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005579 }
5580 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005581 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5582 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005583 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005584 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5585 if (*(args[1]) == 0) {
5586 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005589 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005590 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5591 if (err) {
5592 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5593 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005594 err_code |= ERR_ALERT | ERR_FATAL;
5595 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005596 }
5597 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005598 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5599 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005600 }
5601 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005602 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005603 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005604 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005605
Willy Tarreaubaaee002006-06-26 02:48:02 +02005606 if (curproxy == &defproxy) {
5607 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005608 err_code |= ERR_ALERT | ERR_FATAL;
5609 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005610 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005611 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005612 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005613
Willy Tarreau902636f2013-03-10 19:44:48 +01005614 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005615 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005616 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005617 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005618 goto out;
5619 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005620
5621 proto = protocol_by_family(sk->ss_family);
5622 if (!proto || !proto->connect) {
5623 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5624 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005625 err_code |= ERR_ALERT | ERR_FATAL;
5626 goto out;
5627 }
5628
5629 if (port1 != port2) {
5630 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5631 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005634 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005635
5636 if (!port1) {
5637 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5638 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005639 err_code |= ERR_ALERT | ERR_FATAL;
5640 goto out;
5641 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005642
William Lallemanddf1425a2015-04-28 20:17:49 +02005643 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5644 goto out;
5645
Willy Tarreaud5191e72010-02-09 20:50:45 +01005646 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005647 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005648 }
5649 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005650 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005651 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005652
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005653 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5654 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005655 err_code |= ERR_ALERT | ERR_FATAL;
5656 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005658 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005659 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005660 /**
5661 * The syntax for hash-type config element is
5662 * hash-type {map-based|consistent} [[<algo>] avalanche]
5663 *
5664 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5665 */
5666 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005667
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005668 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5669 err_code |= ERR_WARN;
5670
5671 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005672 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5673 }
5674 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005675 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5676 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005677 else if (strcmp(args[1], "avalanche") == 0) {
5678 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]);
5679 err_code |= ERR_ALERT | ERR_FATAL;
5680 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005681 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005682 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005683 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005684 err_code |= ERR_ALERT | ERR_FATAL;
5685 goto out;
5686 }
Bhaskar98634f02013-10-29 23:30:51 -04005687
5688 /* set the hash function to use */
5689 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005690 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005691 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005692
5693 /* if consistent with no argument, then avalanche modifier is also applied */
5694 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5695 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005696 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005697 /* set the hash function */
5698 if (!strcmp(args[2], "sdbm")) {
5699 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5700 }
5701 else if (!strcmp(args[2], "djb2")) {
5702 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005703 }
5704 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005705 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005706 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005707 else if (!strcmp(args[2], "crc32")) {
5708 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5709 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005710 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005711 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 -05005712 err_code |= ERR_ALERT | ERR_FATAL;
5713 goto out;
5714 }
5715
5716 /* set the hash modifier */
5717 if (!strcmp(args[3], "avalanche")) {
5718 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5719 }
5720 else if (*args[3]) {
5721 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
5724 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005725 }
William Lallemanda73203e2012-03-12 12:48:57 +01005726 }
William Lallemanda73203e2012-03-12 12:48:57 +01005727 else if (strcmp(args[0], "unique-id-format") == 0) {
5728 if (!*(args[1])) {
5729 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5730 err_code |= ERR_ALERT | ERR_FATAL;
5731 goto out;
5732 }
William Lallemand3203ff42012-11-11 17:30:56 +01005733 if (*(args[2])) {
5734 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5735 err_code |= ERR_ALERT | ERR_FATAL;
5736 goto out;
5737 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005738 free(curproxy->conf.uniqueid_format_string);
5739 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005740
Willy Tarreau62a61232013-04-12 18:13:46 +02005741 free(curproxy->conf.uif_file);
5742 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5743 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005744 }
William Lallemanda73203e2012-03-12 12:48:57 +01005745
5746 else if (strcmp(args[0], "unique-id-header") == 0) {
5747 if (!*(args[1])) {
5748 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
5751 }
5752 free(curproxy->header_unique_id);
5753 curproxy->header_unique_id = strdup(args[1]);
5754 }
5755
William Lallemand723b73a2012-02-08 16:37:49 +01005756 else if (strcmp(args[0], "log-format") == 0) {
5757 if (!*(args[1])) {
5758 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5759 err_code |= ERR_ALERT | ERR_FATAL;
5760 goto out;
5761 }
William Lallemand3203ff42012-11-11 17:30:56 +01005762 if (*(args[2])) {
5763 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5764 err_code |= ERR_ALERT | ERR_FATAL;
5765 goto out;
5766 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005767
Willy Tarreau62a61232013-04-12 18:13:46 +02005768 if (curproxy->conf.logformat_string != default_http_log_format &&
5769 curproxy->conf.logformat_string != default_tcp_log_format &&
5770 curproxy->conf.logformat_string != clf_http_log_format)
5771 free(curproxy->conf.logformat_string);
5772 curproxy->conf.logformat_string = strdup(args[1]);
5773
5774 free(curproxy->conf.lfs_file);
5775 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5776 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005777
5778 /* get a chance to improve log-format error reporting by
5779 * reporting the correct line-number when possible.
5780 */
5781 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5782 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5783 file, linenum, curproxy->id);
5784 err_code |= ERR_WARN;
5785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005787 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5788 if (*(args[1]) == 0) {
5789 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
5792 }
5793 free(curproxy->log_tag);
5794 curproxy->log_tag = strdup(args[1]);
5795 }
William Lallemand0f99e342011-10-12 17:50:54 +02005796 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5797 /* delete previous herited or defined syslog servers */
5798 struct logsrv *back;
5799
5800 if (*(args[1]) != 0) {
5801 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5802 err_code |= ERR_ALERT | ERR_FATAL;
5803 goto out;
5804 }
5805
William Lallemand723b73a2012-02-08 16:37:49 +01005806 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5807 LIST_DEL(&tmplogsrv->list);
5808 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005809 }
5810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005811 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005812 struct logsrv *logsrv;
5813
Willy Tarreaubaaee002006-06-26 02:48:02 +02005814 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005815 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005816 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005817 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005818 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005819 LIST_INIT(&node->list);
5820 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5821 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005822 }
5823 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005824 struct sockaddr_storage *sk;
5825 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005826 int arg = 0;
5827 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005828
5829 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005830
Willy Tarreau18324f52014-06-27 18:10:07 +02005831 /* just after the address, a length may be specified */
5832 if (strcmp(args[arg+2], "len") == 0) {
5833 len = atoi(args[arg+3]);
5834 if (len < 80 || len > 65535) {
5835 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5836 file, linenum, args[arg+3]);
5837 err_code |= ERR_ALERT | ERR_FATAL;
5838 goto out;
5839 }
5840 logsrv->maxlen = len;
5841
5842 /* skip these two args */
5843 arg += 2;
5844 }
5845 else
5846 logsrv->maxlen = MAX_SYSLOG_LEN;
5847
5848 if (logsrv->maxlen > global.max_syslog_len) {
5849 global.max_syslog_len = logsrv->maxlen;
5850 logline = realloc(logline, global.max_syslog_len + 1);
5851 }
5852
William Lallemanddf1425a2015-04-28 20:17:49 +02005853 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5854 goto out;
5855
Willy Tarreau18324f52014-06-27 18:10:07 +02005856 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005857 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005858 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005859 err_code |= ERR_ALERT | ERR_FATAL;
5860 goto out;
5861
Willy Tarreaubaaee002006-06-26 02:48:02 +02005862 }
5863
William Lallemand0f99e342011-10-12 17:50:54 +02005864 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005865 if (*(args[arg+3])) {
5866 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005867 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005868 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005869 err_code |= ERR_ALERT | ERR_FATAL;
5870 goto out;
5871
Willy Tarreaubaaee002006-06-26 02:48:02 +02005872 }
5873 }
5874
William Lallemand0f99e342011-10-12 17:50:54 +02005875 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005876 if (*(args[arg+4])) {
5877 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005878 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005879 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005880 err_code |= ERR_ALERT | ERR_FATAL;
5881 goto out;
5882
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005883 }
5884 }
5885
Willy Tarreau902636f2013-03-10 19:44:48 +01005886 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005887 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005888 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005889 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005890 goto out;
5891 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005892
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005893 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005894
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005895 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005896 if (port1 != port2) {
5897 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5898 file, linenum, args[0], args[1]);
5899 err_code |= ERR_ALERT | ERR_FATAL;
5900 goto out;
5901 }
5902
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005903 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005904 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005905 }
William Lallemand0f99e342011-10-12 17:50:54 +02005906
5907 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005908 }
5909 else {
5910 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5911 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005914 }
5915 }
5916 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005917 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005918 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005919 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005920 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005921
Willy Tarreau977b8e42006-12-29 14:19:17 +01005922 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005923 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005924
Willy Tarreaubaaee002006-06-26 02:48:02 +02005925 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005926 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5927 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005930 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005931
5932 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005933 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5934 free(curproxy->conn_src.iface_name);
5935 curproxy->conn_src.iface_name = NULL;
5936 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005937
Willy Tarreau902636f2013-03-10 19:44:48 +01005938 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005939 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005940 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005941 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005942 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005943 goto out;
5944 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005945
5946 proto = protocol_by_family(sk->ss_family);
5947 if (!proto || !proto->connect) {
5948 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005949 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005950 err_code |= ERR_ALERT | ERR_FATAL;
5951 goto out;
5952 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005953
5954 if (port1 != port2) {
5955 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5956 file, linenum, args[0], args[1]);
5957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
5959 }
5960
Willy Tarreauef9a3602012-12-08 22:29:20 +01005961 curproxy->conn_src.source_addr = *sk;
5962 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005963
5964 cur_arg = 2;
5965 while (*(args[cur_arg])) {
5966 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005967#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5968#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005969 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005970 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5971 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005972 err_code |= ERR_ALERT | ERR_FATAL;
5973 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005974 }
5975#endif
5976 if (!*args[cur_arg + 1]) {
5977 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5978 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005981 }
5982
5983 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005984 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5985 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005986 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005987 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5988 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005989 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5990 char *name, *end;
5991
5992 name = args[cur_arg+1] + 7;
5993 while (isspace(*name))
5994 name++;
5995
5996 end = name;
5997 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5998 end++;
5999
Willy Tarreauef9a3602012-12-08 22:29:20 +01006000 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6001 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6002 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6003 curproxy->conn_src.bind_hdr_len = end - name;
6004 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6005 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6006 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006007
6008 /* now look for an occurrence number */
6009 while (isspace(*end))
6010 end++;
6011 if (*end == ',') {
6012 end++;
6013 name = end;
6014 if (*end == '-')
6015 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006016 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006017 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006018 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006019 }
6020
Willy Tarreauef9a3602012-12-08 22:29:20 +01006021 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006022 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6023 " occurrences values smaller than %d.\n",
6024 file, linenum, MAX_HDR_HISTORY);
6025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
6027 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006028 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006029 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006030
Willy Tarreau902636f2013-03-10 19:44:48 +01006031 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006032 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006033 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006034 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006035 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006036 goto out;
6037 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006038
6039 proto = protocol_by_family(sk->ss_family);
6040 if (!proto || !proto->connect) {
6041 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6042 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006043 err_code |= ERR_ALERT | ERR_FATAL;
6044 goto out;
6045 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006046
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006047 if (port1 != port2) {
6048 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6049 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006050 err_code |= ERR_ALERT | ERR_FATAL;
6051 goto out;
6052 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006053 curproxy->conn_src.tproxy_addr = *sk;
6054 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006055 }
6056 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02006057#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006058 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006059#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006060#else /* no TPROXY support */
6061 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006062 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006063 err_code |= ERR_ALERT | ERR_FATAL;
6064 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006065#endif
6066 cur_arg += 2;
6067 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006068 }
6069
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006070 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6071#ifdef SO_BINDTODEVICE
6072 if (!*args[cur_arg + 1]) {
6073 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6074 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006075 err_code |= ERR_ALERT | ERR_FATAL;
6076 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006077 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006078 free(curproxy->conn_src.iface_name);
6079 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6080 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006081 global.last_checks |= LSTCHK_NETADM;
6082#else
6083 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6084 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006085 err_code |= ERR_ALERT | ERR_FATAL;
6086 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006087#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006088 cur_arg += 2;
6089 continue;
6090 }
6091 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006092 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006093 err_code |= ERR_ALERT | ERR_FATAL;
6094 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006096 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006097 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6098 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6099 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006100 err_code |= ERR_ALERT | ERR_FATAL;
6101 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006103 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006104 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6106 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006107 err_code |= ERR_ALERT | ERR_FATAL;
6108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006109 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006110
6111 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006112 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006113 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006114 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006116 }
6117 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006118 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006119 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006120 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006121 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006123 }
6124 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006125 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006126 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006127 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006128 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006129 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006130 }
6131 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006132 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006133 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006134 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006135 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006136 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006137 }
6138 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006139 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006140 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006141 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006142 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006143 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006144 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006145 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006146 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006147 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006148 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006149 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006150 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006151 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006152 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006153 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006154 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6155 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006156 err_code |= ERR_ALERT | ERR_FATAL;
6157 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006158 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006159
6160 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006161 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006162 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006163 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006164 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006165 }
6166 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006167 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006168 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006169 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006170 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006172 }
6173 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006174 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006175 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006176 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006177 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006178 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 }
6180 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006181 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006182 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006183 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006184 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006185 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006186 }
6187 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006188 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006189 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006190 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006191 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006192 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006193 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006194 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006195 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006196 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006197 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006198 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006199 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006200 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006201 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006202 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006203
Willy Tarreaubaaee002006-06-26 02:48:02 +02006204 if (curproxy == &defproxy) {
6205 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006206 err_code |= ERR_ALERT | ERR_FATAL;
6207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006208 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006209 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006210 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006211
Willy Tarreaubaaee002006-06-26 02:48:02 +02006212 if (*(args[1]) == 0) {
6213 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006214 err_code |= ERR_ALERT | ERR_FATAL;
6215 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006216 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006217
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006218 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006219 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6220 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6221 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006222 err_code |= ERR_ALERT | ERR_FATAL;
6223 goto out;
6224 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006225 err_code |= warnif_cond_conflicts(cond,
6226 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6227 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006228 }
6229 else if (*args[2]) {
6230 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6231 file, linenum, args[0], args[2]);
6232 err_code |= ERR_ALERT | ERR_FATAL;
6233 goto out;
6234 }
6235
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006236 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006237 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006238 wl->s = strdup(args[1]);
6239 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006240 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006241 }
6242 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006243 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006244 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6245 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006246 err_code |= ERR_ALERT | ERR_FATAL;
6247 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006248 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006249
Willy Tarreauade5ec42010-01-28 19:33:49 +01006250 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006251 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006252 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006253 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006254 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006255 }
6256 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006257 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006258 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006259 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006260 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006261 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006262 }
6263 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006264 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006265 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006266 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006267 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006268 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006269 }
6270 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006271 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006272 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6273 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006274 err_code |= ERR_ALERT | ERR_FATAL;
6275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006276 }
6277
Willy Tarreauade5ec42010-01-28 19:33:49 +01006278 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006279 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006280 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006281 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006282 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006283 }
6284 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006285 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006286 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006287 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006288 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006289 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006290 }
6291 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006292 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006293 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006294 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006295 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006296 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006297 }
6298 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006299 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006300
Willy Tarreaubaaee002006-06-26 02:48:02 +02006301 if (curproxy == &defproxy) {
6302 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006303 err_code |= ERR_ALERT | ERR_FATAL;
6304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006305 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006306 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006307 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006308
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 if (*(args[1]) == 0) {
6310 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006311 err_code |= ERR_ALERT | ERR_FATAL;
6312 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006313 }
6314
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006315 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006316 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6317 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6318 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006319 err_code |= ERR_ALERT | ERR_FATAL;
6320 goto out;
6321 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006322 err_code |= warnif_cond_conflicts(cond,
6323 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6324 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006325 }
6326 else if (*args[2]) {
6327 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6328 file, linenum, args[0], args[2]);
6329 err_code |= ERR_ALERT | ERR_FATAL;
6330 goto out;
6331 }
6332
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006333 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006334 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006335 wl->s = strdup(args[1]);
6336 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
6338 else if (!strcmp(args[0], "errorloc") ||
6339 !strcmp(args[0], "errorloc302") ||
6340 !strcmp(args[0], "errorloc303")) { /* error location */
6341 int errnum, errlen;
6342 char *err;
6343
Willy Tarreau977b8e42006-12-29 14:19:17 +01006344 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006345 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006346
Willy Tarreaubaaee002006-06-26 02:48:02 +02006347 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006348 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006349 err_code |= ERR_ALERT | ERR_FATAL;
6350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352
6353 errnum = atol(args[1]);
6354 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006355 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6356 err = malloc(errlen);
6357 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006359 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6360 err = malloc(errlen);
6361 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006362 }
6363
Willy Tarreau0f772532006-12-23 20:51:41 +01006364 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6365 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006366 chunk_destroy(&curproxy->errmsg[rc]);
6367 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006368 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006369 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006370 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006371
6372 if (rc >= HTTP_ERR_SIZE) {
6373 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6374 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006375 free(err);
6376 }
6377 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006378 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6379 int errnum, errlen, fd;
6380 char *err;
6381 struct stat stat;
6382
6383 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006384 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006385
6386 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006387 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006388 err_code |= ERR_ALERT | ERR_FATAL;
6389 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006390 }
6391
6392 fd = open(args[2], O_RDONLY);
6393 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6394 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6395 file, linenum, args[2], args[1]);
6396 if (fd >= 0)
6397 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006398 err_code |= ERR_ALERT | ERR_FATAL;
6399 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006400 }
6401
Willy Tarreau27a674e2009-08-17 07:23:33 +02006402 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006403 errlen = stat.st_size;
6404 } else {
6405 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006406 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006407 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006408 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006409 }
6410
6411 err = malloc(errlen); /* malloc() must succeed during parsing */
6412 errnum = read(fd, err, errlen);
6413 if (errnum != errlen) {
6414 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6415 file, linenum, args[2], args[1]);
6416 close(fd);
6417 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006418 err_code |= ERR_ALERT | ERR_FATAL;
6419 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006420 }
6421 close(fd);
6422
6423 errnum = atol(args[1]);
6424 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6425 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006426 chunk_destroy(&curproxy->errmsg[rc]);
6427 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006428 break;
6429 }
6430 }
6431
6432 if (rc >= HTTP_ERR_SIZE) {
6433 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6434 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006435 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006436 free(err);
6437 }
6438 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006439 else if (!strcmp(args[0], "compression")) {
6440 struct comp *comp;
6441 if (curproxy->comp == NULL) {
6442 comp = calloc(1, sizeof(struct comp));
6443 curproxy->comp = comp;
6444 } else {
6445 comp = curproxy->comp;
6446 }
6447
6448 if (!strcmp(args[1], "algo")) {
6449 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006450 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006451
William Lallemand82fe75c2012-10-23 10:25:10 +02006452 cur_arg = 2;
6453 if (!*args[cur_arg]) {
6454 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6455 file, linenum, args[0]);
6456 err_code |= ERR_ALERT | ERR_FATAL;
6457 goto out;
6458 }
6459 while (*(args[cur_arg])) {
6460 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6461 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6462 file, linenum, args[0], args[cur_arg]);
6463 err_code |= ERR_ALERT | ERR_FATAL;
6464 goto out;
6465 }
William Lallemand552df672012-11-07 13:21:47 +01006466 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6467 curproxy->comp->algos->end(&ctx);
6468 } else {
6469 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6470 file, linenum, args[0], args[cur_arg]);
6471 err_code |= ERR_ALERT | ERR_FATAL;
6472 goto out;
6473 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006474 cur_arg ++;
6475 continue;
6476 }
6477 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006478 else if (!strcmp(args[1], "offload")) {
6479 comp->offload = 1;
6480 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006481 else if (!strcmp(args[1], "type")) {
6482 int cur_arg;
6483 cur_arg = 2;
6484 if (!*args[cur_arg]) {
6485 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6486 file, linenum, args[0]);
6487 err_code |= ERR_ALERT | ERR_FATAL;
6488 goto out;
6489 }
6490 while (*(args[cur_arg])) {
6491 comp_append_type(comp, args[cur_arg]);
6492 cur_arg ++;
6493 continue;
6494 }
6495 }
6496 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006497 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006498 file, linenum, args[0]);
6499 err_code |= ERR_ALERT | ERR_FATAL;
6500 goto out;
6501 }
6502 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006503 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006504 struct cfg_kw_list *kwl;
6505 int index;
6506
6507 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6508 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6509 if (kwl->kw[index].section != CFG_LISTEN)
6510 continue;
6511 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6512 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006513 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006514 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006515 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006516 err_code |= ERR_ALERT | ERR_FATAL;
6517 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006518 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006519 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006520 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006521 err_code |= ERR_WARN;
6522 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006523 }
Willy Tarreau93893792009-07-23 13:19:11 +02006524 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006525 }
6526 }
6527 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006528
Willy Tarreau6daf3432008-01-22 16:44:08 +01006529 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006530 err_code |= ERR_ALERT | ERR_FATAL;
6531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006532 }
Willy Tarreau93893792009-07-23 13:19:11 +02006533 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006534 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006535 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006536}
6537
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006538int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006539cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6540{
6541#ifdef CONFIG_HAP_NS
6542 const char *err;
6543 const char *item = args[0];
6544
6545 if (!strcmp(item, "namespace_list")) {
6546 return 0;
6547 }
6548 else if (!strcmp(item, "namespace")) {
6549 size_t idx = 1;
6550 const char *current;
6551 while (*(current = args[idx++])) {
6552 err = invalid_char(current);
6553 if (err) {
6554 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6555 file, linenum, *err, item, current);
6556 return ERR_ALERT | ERR_FATAL;
6557 }
6558
6559 if (netns_store_lookup(current, strlen(current))) {
6560 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6561 file, linenum, current);
6562 return ERR_ALERT | ERR_FATAL;
6563 }
6564 if (!netns_store_insert(current)) {
6565 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6566 file, linenum, current);
6567 return ERR_ALERT | ERR_FATAL;
6568 }
6569 }
6570 }
6571
6572 return 0;
6573#else
6574 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6575 file, linenum);
6576 return ERR_ALERT | ERR_FATAL;
6577#endif
6578}
6579
6580int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006581cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6582{
6583
6584 int err_code = 0;
6585 const char *err;
6586
6587 if (!strcmp(args[0], "userlist")) { /* new userlist */
6588 struct userlist *newul;
6589
6590 if (!*args[1]) {
6591 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6592 file, linenum, args[0]);
6593 err_code |= ERR_ALERT | ERR_FATAL;
6594 goto out;
6595 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006596 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6597 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006598
6599 err = invalid_char(args[1]);
6600 if (err) {
6601 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6602 file, linenum, *err, args[0], args[1]);
6603 err_code |= ERR_ALERT | ERR_FATAL;
6604 goto out;
6605 }
6606
6607 for (newul = userlist; newul; newul = newul->next)
6608 if (!strcmp(newul->name, args[1])) {
6609 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6610 file, linenum, args[1]);
6611 err_code |= ERR_WARN;
6612 goto out;
6613 }
6614
6615 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6616 if (!newul) {
6617 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6618 err_code |= ERR_ALERT | ERR_ABORT;
6619 goto out;
6620 }
6621
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006622 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006623 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006624 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6625 err_code |= ERR_ALERT | ERR_ABORT;
6626 goto out;
6627 }
6628
6629 newul->next = userlist;
6630 userlist = newul;
6631
6632 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006633 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006634 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006635 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006636
6637 if (!*args[1]) {
6638 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6639 file, linenum, args[0]);
6640 err_code |= ERR_ALERT | ERR_FATAL;
6641 goto out;
6642 }
6643
6644 err = invalid_char(args[1]);
6645 if (err) {
6646 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6647 file, linenum, *err, args[0], args[1]);
6648 err_code |= ERR_ALERT | ERR_FATAL;
6649 goto out;
6650 }
6651
William Lallemand4ac9f542015-05-28 18:03:51 +02006652 if (!userlist)
6653 goto out;
6654
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006655 for (ag = userlist->groups; ag; ag = ag->next)
6656 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006657 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6658 file, linenum, args[1], userlist->name);
6659 err_code |= ERR_ALERT;
6660 goto out;
6661 }
6662
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006663 ag = calloc(1, sizeof(*ag));
6664 if (!ag) {
6665 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6666 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006667 goto out;
6668 }
6669
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006670 ag->name = strdup(args[1]);
6671 if (!ag) {
6672 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6673 err_code |= ERR_ALERT | ERR_ABORT;
6674 goto out;
6675 }
6676
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006677 cur_arg = 2;
6678
6679 while (*args[cur_arg]) {
6680 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006681 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006682 cur_arg += 2;
6683 continue;
6684 } else {
6685 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6686 file, linenum, args[0]);
6687 err_code |= ERR_ALERT | ERR_FATAL;
6688 goto out;
6689 }
6690 }
6691
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006692 ag->next = userlist->groups;
6693 userlist->groups = ag;
6694
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006695 } else if (!strcmp(args[0], "user")) { /* new user */
6696 struct auth_users *newuser;
6697 int cur_arg;
6698
6699 if (!*args[1]) {
6700 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6701 file, linenum, args[0]);
6702 err_code |= ERR_ALERT | ERR_FATAL;
6703 goto out;
6704 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006705 if (!userlist)
6706 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006707
6708 for (newuser = userlist->users; newuser; newuser = newuser->next)
6709 if (!strcmp(newuser->user, args[1])) {
6710 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6711 file, linenum, args[1], userlist->name);
6712 err_code |= ERR_ALERT;
6713 goto out;
6714 }
6715
6716 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6717 if (!newuser) {
6718 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6719 err_code |= ERR_ALERT | ERR_ABORT;
6720 goto out;
6721 }
6722
6723 newuser->user = strdup(args[1]);
6724
6725 newuser->next = userlist->users;
6726 userlist->users = newuser;
6727
6728 cur_arg = 2;
6729
6730 while (*args[cur_arg]) {
6731 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006732#ifdef CONFIG_HAP_CRYPT
6733 if (!crypt("", args[cur_arg + 1])) {
6734 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6735 file, linenum, newuser->user);
6736 err_code |= ERR_ALERT | ERR_FATAL;
6737 goto out;
6738 }
6739#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006740 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6741 file, linenum);
6742 err_code |= ERR_ALERT;
6743#endif
6744 newuser->pass = strdup(args[cur_arg + 1]);
6745 cur_arg += 2;
6746 continue;
6747 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6748 newuser->pass = strdup(args[cur_arg + 1]);
6749 newuser->flags |= AU_O_INSECURE;
6750 cur_arg += 2;
6751 continue;
6752 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006753 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006754 cur_arg += 2;
6755 continue;
6756 } else {
6757 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6758 file, linenum, args[0]);
6759 err_code |= ERR_ALERT | ERR_FATAL;
6760 goto out;
6761 }
6762 }
6763 } else {
6764 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6765 err_code |= ERR_ALERT | ERR_FATAL;
6766 }
6767
6768out:
6769 return err_code;
6770}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006771
6772/*
6773 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006774 * Returns the error code, 0 if OK, or any combination of :
6775 * - ERR_ABORT: must abort ASAP
6776 * - ERR_FATAL: we can continue parsing but not start the service
6777 * - ERR_WARN: a warning has been emitted
6778 * - ERR_ALERT: an alert has been emitted
6779 * Only the two first ones can stop processing, the two others are just
6780 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006781 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006782int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006783{
William Lallemand64e84512015-05-12 14:25:37 +02006784 char *thisline;
6785 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006786 FILE *f;
6787 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006788 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006789 struct cfg_section *cs = NULL;
6790 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006791 int readbytes = 0;
6792
6793 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006794 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006795 return -1;
6796 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006797
6798 /* Register internal sections */
6799 if (!cfg_register_section("listen", cfg_parse_listen) ||
6800 !cfg_register_section("frontend", cfg_parse_listen) ||
6801 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006802 !cfg_register_section("defaults", cfg_parse_listen) ||
6803 !cfg_register_section("global", cfg_parse_global) ||
6804 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006805 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006806 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006807 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6808 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006809 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006810
Willy Tarreaubaaee002006-06-26 02:48:02 +02006811 if ((f=fopen(file,"r")) == NULL)
6812 return -1;
6813
William Lallemandb2f07452015-05-12 14:27:13 +02006814next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006815 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006816 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006817 char *end;
6818 char *args[MAX_LINE_ARGS + 1];
6819 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006820 int dquote = 0; /* double quote */
6821 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006822
Willy Tarreaubaaee002006-06-26 02:48:02 +02006823 linenum++;
6824
6825 end = line + strlen(line);
6826
William Lallemand64e84512015-05-12 14:25:37 +02006827 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006828 /* Check if we reached the limit and the last char is not \n.
6829 * Watch out for the last line without the terminating '\n'!
6830 */
William Lallemand64e84512015-05-12 14:25:37 +02006831 char *newline;
6832 int newlinesize = linesize * 2;
6833
6834 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6835 if (newline == NULL) {
6836 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6837 file, linenum);
6838 err_code |= ERR_ALERT | ERR_FATAL;
6839 continue;
6840 }
6841
6842 readbytes = linesize - 1;
6843 linesize = newlinesize;
6844 thisline = newline;
6845 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006846 }
6847
William Lallemand64e84512015-05-12 14:25:37 +02006848 readbytes = 0;
6849
Willy Tarreaubaaee002006-06-26 02:48:02 +02006850 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006851 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006852 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006853
Willy Tarreaubaaee002006-06-26 02:48:02 +02006854 arg = 0;
6855 args[arg] = line;
6856
6857 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006858 if (*line == '"' && !squote) { /* double quote outside single quotes */
6859 if (dquote)
6860 dquote = 0;
6861 else
6862 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006863 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006864 end--;
6865 }
6866 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6867 if (squote)
6868 squote = 0;
6869 else
6870 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006871 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006872 end--;
6873 }
6874 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006875 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6876 * C equivalent value. Other combinations left unchanged (eg: \1).
6877 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006878 int skip = 0;
6879 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6880 *line = line[1];
6881 skip = 1;
6882 }
6883 else if (line[1] == 'r') {
6884 *line = '\r';
6885 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006886 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006887 else if (line[1] == 'n') {
6888 *line = '\n';
6889 skip = 1;
6890 }
6891 else if (line[1] == 't') {
6892 *line = '\t';
6893 skip = 1;
6894 }
6895 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006896 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006897 unsigned char hex1, hex2;
6898 hex1 = toupper(line[2]) - '0';
6899 hex2 = toupper(line[3]) - '0';
6900 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6901 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6902 *line = (hex1<<4) + hex2;
6903 skip = 3;
6904 }
6905 else {
6906 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006907 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006908 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006909 } else if (line[1] == '"') {
6910 *line = '"';
6911 skip = 1;
6912 } else if (line[1] == '\'') {
6913 *line = '\'';
6914 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006915 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6916 *line = '$';
6917 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006918 }
6919 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006920 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006921 end -= skip;
6922 }
6923 line++;
6924 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006925 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006926 /* end of string, end of loop */
6927 *line = 0;
6928 break;
6929 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006930 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006931 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006932 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006933 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006934 line++;
6935 args[++arg] = line;
6936 }
William Lallemandb2f07452015-05-12 14:27:13 +02006937 else if (dquote && *line == '$') {
6938 /* environment variables are evaluated inside double quotes */
6939 char *var_beg;
6940 char *var_end;
6941 char save_char;
6942 char *value;
6943 int val_len;
6944 int newlinesize;
6945 int braces = 0;
6946
6947 var_beg = line + 1;
6948 var_end = var_beg;
6949
6950 if (*var_beg == '{') {
6951 var_beg++;
6952 var_end++;
6953 braces = 1;
6954 }
6955
6956 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6957 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6958 err_code |= ERR_ALERT | ERR_FATAL;
6959 goto next_line; /* skip current line */
6960 }
6961
6962 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6963 var_end++;
6964
6965 save_char = *var_end;
6966 *var_end = '\0';
6967 value = getenv(var_beg);
6968 *var_end = save_char;
6969 val_len = value ? strlen(value) : 0;
6970
6971 if (braces) {
6972 if (*var_end == '}') {
6973 var_end++;
6974 braces = 0;
6975 } else {
6976 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6977 err_code |= ERR_ALERT | ERR_FATAL;
6978 goto next_line; /* skip current line */
6979 }
6980 }
6981
6982 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6983
6984 /* if not enough space in thisline */
6985 if (newlinesize > linesize) {
6986 char *newline;
6987
6988 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6989 if (newline == NULL) {
6990 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6991 err_code |= ERR_ALERT | ERR_FATAL;
6992 goto next_line; /* slip current line */
6993 }
6994 /* recompute pointers if realloc returns a new pointer */
6995 if (newline != thisline) {
6996 int i;
6997 int diff;
6998
6999 for (i = 0; i <= arg; i++) {
7000 diff = args[i] - thisline;
7001 args[i] = newline + diff;
7002 }
7003
7004 diff = var_end - thisline;
7005 var_end = newline + diff;
7006 diff = end - thisline;
7007 end = newline + diff;
7008 diff = line - thisline;
7009 line = newline + diff;
7010 thisline = newline;
7011 }
7012 linesize = newlinesize;
7013 }
7014
7015 /* insert value inside the line */
7016 memmove(line + val_len, var_end, end - var_end + 1);
7017 memcpy(line, value, val_len);
7018 end += val_len - (var_end - line);
7019 line += val_len;
7020 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007021 else {
7022 line++;
7023 }
7024 }
William Lallemandb2f07452015-05-12 14:27:13 +02007025
William Lallemandf9873ba2015-05-05 17:37:14 +02007026 if (dquote) {
7027 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7028 err_code |= ERR_ALERT | ERR_FATAL;
7029 }
7030
7031 if (squote) {
7032 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7033 err_code |= ERR_ALERT | ERR_FATAL;
7034 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007035
7036 /* empty line */
7037 if (!**args)
7038 continue;
7039
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007040 if (*line) {
7041 /* we had to stop due to too many args.
7042 * Let's terminate the string, print the offending part then cut the
7043 * last arg.
7044 */
7045 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7046 line++;
7047 *line = '\0';
7048
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007049 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007050 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007051 err_code |= ERR_ALERT | ERR_FATAL;
7052 args[arg] = line;
7053 }
7054
Willy Tarreau540abe42007-05-02 20:50:16 +02007055 /* zero out remaining args and ensure that at least one entry
7056 * is zeroed out.
7057 */
7058 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007059 args[arg] = line;
7060 }
7061
Willy Tarreau3842f002009-06-14 11:39:52 +02007062 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007063 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007064 char *tmp;
7065
Willy Tarreau3842f002009-06-14 11:39:52 +02007066 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007067 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007068 for (arg=0; *args[arg+1]; arg++)
7069 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007070 *tmp = '\0'; // fix the next arg to \0
7071 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007072 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007073 else if (!strcmp(args[0], "default")) {
7074 kwm = KWM_DEF;
7075 for (arg=0; *args[arg+1]; arg++)
7076 args[arg] = args[arg+1]; // shift args after inversion
7077 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007078
William Lallemand0f99e342011-10-12 17:50:54 +02007079 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7080 strcmp(args[0], "log") != 0) {
7081 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007082 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007083 }
7084
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007085 /* detect section start */
7086 list_for_each_entry(ics, &sections, list) {
7087 if (strcmp(args[0], ics->section_name) == 0) {
7088 cursection = ics->section_name;
7089 cs = ics;
7090 break;
7091 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007092 }
7093
Willy Tarreaubaaee002006-06-26 02:48:02 +02007094 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007095 if (cs)
7096 err_code |= cs->section_parser(file, linenum, args, kwm);
7097 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007098 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007099 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007100 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007101
7102 if (err_code & ERR_ABORT)
7103 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007105 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007106 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007107 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007108 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007109}
7110
Willy Tarreau64ab6072014-09-16 12:17:36 +02007111/* This function propagates processes from frontend <from> to backend <to> so
7112 * that it is always guaranteed that a backend pointed to by a frontend is
7113 * bound to all of its processes. After that, if the target is a "listen"
7114 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007115 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007116 * checked first to ensure that <to> is already bound to all processes of
7117 * <from>, there is no risk of looping and we ensure to follow the shortest
7118 * path to the destination.
7119 *
7120 * It is possible to set <to> to NULL for the first call so that the function
7121 * takes care of visiting the initial frontend in <from>.
7122 *
7123 * It is important to note that the function relies on the fact that all names
7124 * have already been resolved.
7125 */
7126void propagate_processes(struct proxy *from, struct proxy *to)
7127{
7128 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007129
7130 if (to) {
7131 /* check whether we need to go down */
7132 if (from->bind_proc &&
7133 (from->bind_proc & to->bind_proc) == from->bind_proc)
7134 return;
7135
7136 if (!from->bind_proc && !to->bind_proc)
7137 return;
7138
7139 to->bind_proc = from->bind_proc ?
7140 (to->bind_proc | from->bind_proc) : 0;
7141
7142 /* now propagate down */
7143 from = to;
7144 }
7145
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007146 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007147 return;
7148
Willy Tarreauf6b70012014-12-18 14:00:43 +01007149 if (from->state == PR_STSTOPPED)
7150 return;
7151
Willy Tarreau64ab6072014-09-16 12:17:36 +02007152 /* default_backend */
7153 if (from->defbe.be)
7154 propagate_processes(from, from->defbe.be);
7155
7156 /* use_backend */
7157 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007158 if (rule->dynamic)
7159 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007160 to = rule->be.backend;
7161 propagate_processes(from, to);
7162 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007163}
7164
Willy Tarreaubb925012009-07-23 13:36:36 +02007165/*
7166 * Returns the error code, 0 if OK, or any combination of :
7167 * - ERR_ABORT: must abort ASAP
7168 * - ERR_FATAL: we can continue parsing but not start the service
7169 * - ERR_WARN: a warning has been emitted
7170 * - ERR_ALERT: an alert has been emitted
7171 * Only the two first ones can stop processing, the two others are just
7172 * indicators.
7173 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007174int check_config_validity()
7175{
7176 int cfgerr = 0;
7177 struct proxy *curproxy = NULL;
7178 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007179 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007180 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007181 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007182
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007183 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007184 /*
7185 * Now, check for the integrity of all that we have collected.
7186 */
7187
7188 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007189 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007190
Willy Tarreau193b8c62012-11-22 00:17:38 +01007191 if (!global.tune.max_http_hdr)
7192 global.tune.max_http_hdr = MAX_HTTP_HDR;
7193
7194 if (!global.tune.cookie_len)
7195 global.tune.cookie_len = CAPTURE_LEN;
7196
7197 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7198
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007199 /* Post initialisation of the users and groups lists. */
7200 err_code = userlist_postinit();
7201 if (err_code != ERR_NONE)
7202 goto out;
7203
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007204 /* first, we will invert the proxy list order */
7205 curproxy = NULL;
7206 while (proxy) {
7207 struct proxy *next;
7208
7209 next = proxy->next;
7210 proxy->next = curproxy;
7211 curproxy = proxy;
7212 if (!next)
7213 break;
7214 proxy = next;
7215 }
7216
Willy Tarreau419ead82014-09-16 13:41:21 +02007217 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007218 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007219 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007220 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007221 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02007222 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007223 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007224 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007225
Willy Tarreau050536d2012-10-04 08:47:34 +02007226 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007227 /* proxy ID not set, use automatic numbering with first
7228 * spare entry starting with next_pxid.
7229 */
7230 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7231 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7232 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007233 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007234 next_pxid++;
7235
Willy Tarreau55ea7572007-06-17 19:56:27 +02007236
Willy Tarreaubaaee002006-06-26 02:48:02 +02007237 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007238 /* ensure we don't keep listeners uselessly bound */
7239 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007240 free((void *)curproxy->table.peers.name);
7241 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007242 continue;
7243 }
7244
Willy Tarreau102df612014-05-07 23:56:38 +02007245 /* Check multi-process mode compatibility for the current proxy */
7246
7247 if (curproxy->bind_proc) {
7248 /* an explicit bind-process was specified, let's check how many
7249 * processes remain.
7250 */
David Carliere6c39412015-07-02 07:00:17 +00007251 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007252
7253 curproxy->bind_proc &= nbits(global.nbproc);
7254 if (!curproxy->bind_proc && nbproc == 1) {
7255 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);
7256 curproxy->bind_proc = 1;
7257 }
7258 else if (!curproxy->bind_proc && nbproc > 1) {
7259 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);
7260 curproxy->bind_proc = 0;
7261 }
7262 }
7263
Willy Tarreau3d209582014-05-09 17:06:11 +02007264 /* check and reduce the bind-proc of each listener */
7265 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7266 unsigned long mask;
7267
7268 if (!bind_conf->bind_proc)
7269 continue;
7270
7271 mask = nbits(global.nbproc);
7272 if (curproxy->bind_proc)
7273 mask &= curproxy->bind_proc;
7274 /* mask cannot be null here thanks to the previous checks */
7275
David Carliere6c39412015-07-02 07:00:17 +00007276 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007277 bind_conf->bind_proc &= mask;
7278
7279 if (!bind_conf->bind_proc && nbproc == 1) {
7280 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",
7281 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7282 bind_conf->bind_proc = mask & ~(mask - 1);
7283 }
7284 else if (!bind_conf->bind_proc && nbproc > 1) {
7285 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",
7286 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7287 bind_conf->bind_proc = 0;
7288 }
7289 }
7290
Willy Tarreauff01a212009-03-15 13:46:16 +01007291 switch (curproxy->mode) {
7292 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007293 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007294 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007295 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7296 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007297 cfgerr++;
7298 }
7299
7300 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007301 Warning("config : servers will be ignored for %s '%s'.\n",
7302 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007303 break;
7304
7305 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007306 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007307 break;
7308
7309 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007310 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007311 break;
7312 }
7313
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007314 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007315 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007316 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007317 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7318 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007319 cfgerr++;
7320 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007321#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007322 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007323 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7324 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007325 cfgerr++;
7326 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007327#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007328 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007329 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7330 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007331 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007332 }
7333 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007334 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007335 /* If no LB algo is set in a backend, and we're not in
7336 * transparent mode, dispatch mode nor proxy mode, we
7337 * want to use balance roundrobin by default.
7338 */
7339 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7340 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007341 }
7342 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007343
Willy Tarreau1620ec32011-08-06 17:05:02 +02007344 if (curproxy->options & PR_O_DISPATCH)
7345 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7346 else if (curproxy->options & PR_O_HTTP_PROXY)
7347 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7348 else if (curproxy->options & PR_O_TRANSP)
7349 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007350
Willy Tarreau1620ec32011-08-06 17:05:02 +02007351 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7352 if (curproxy->options & PR_O_DISABLE404) {
7353 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7354 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7355 err_code |= ERR_WARN;
7356 curproxy->options &= ~PR_O_DISABLE404;
7357 }
7358 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7359 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7360 "send-state", proxy_type_str(curproxy), curproxy->id);
7361 err_code |= ERR_WARN;
7362 curproxy->options &= ~PR_O2_CHK_SNDST;
7363 }
Willy Tarreauef781042010-01-27 11:53:01 +01007364 }
7365
Simon Horman98637e52014-06-20 12:30:16 +09007366 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7367 if (!global.external_check) {
7368 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7369 curproxy->id, "option external-check");
7370 cfgerr++;
7371 }
7372 if (!curproxy->check_command) {
7373 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7374 curproxy->id, "option external-check");
7375 cfgerr++;
7376 }
7377 }
7378
Simon Horman64e34162015-02-06 11:11:57 +09007379 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007380 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7381 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09007382 "'email-alert from', 'email-alert level' 'email-alert mailer', "
7383 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007384 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
7385 "to be present).\n",
7386 proxy_type_str(curproxy), curproxy->id);
7387 err_code |= ERR_WARN;
7388 free_email_alert(curproxy);
7389 }
7390 if (!curproxy->email_alert.myhostname)
7391 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007392 }
7393
Simon Horman98637e52014-06-20 12:30:16 +09007394 if (curproxy->check_command) {
7395 int clear = 0;
7396 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7397 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7398 "external-check command", proxy_type_str(curproxy), curproxy->id);
7399 err_code |= ERR_WARN;
7400 clear = 1;
7401 }
7402 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7403 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7404 curproxy->id, "external-check command");
7405 cfgerr++;
7406 }
7407 if (clear) {
7408 free(curproxy->check_command);
7409 curproxy->check_command = NULL;
7410 }
7411 }
7412
7413 if (curproxy->check_path) {
7414 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7415 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7416 "external-check path", proxy_type_str(curproxy), curproxy->id);
7417 err_code |= ERR_WARN;
7418 free(curproxy->check_path);
7419 curproxy->check_path = NULL;
7420 }
7421 }
7422
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007423 /* if a default backend was specified, let's find it */
7424 if (curproxy->defbe.name) {
7425 struct proxy *target;
7426
Willy Tarreauafb39922015-05-26 12:04:09 +02007427 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007428 if (!target) {
7429 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7430 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007431 cfgerr++;
7432 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007433 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7434 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007435 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007436 } else if (target->mode != curproxy->mode &&
7437 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7438
7439 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7440 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7441 curproxy->conf.file, curproxy->conf.line,
7442 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7443 target->conf.file, target->conf.line);
7444 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007445 } else {
7446 free(curproxy->defbe.name);
7447 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007448
7449 /* Emit a warning if this proxy also has some servers */
7450 if (curproxy->srv) {
7451 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7452 curproxy->id);
7453 err_code |= ERR_WARN;
7454 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007455 }
7456 }
7457
Willy Tarreau55ea7572007-06-17 19:56:27 +02007458 /* find the target proxy for 'use_backend' rules */
7459 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007460 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007461 struct logformat_node *node;
7462 char *pxname;
7463
7464 /* Try to parse the string as a log format expression. If the result
7465 * of the parsing is only one entry containing a simple string, then
7466 * it's a standard string corresponding to a static rule, thus the
7467 * parsing is cancelled and be.name is restored to be resolved.
7468 */
7469 pxname = rule->be.name;
7470 LIST_INIT(&rule->be.expr);
7471 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7472 curproxy->conf.args.file, curproxy->conf.args.line);
7473 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7474
7475 if (!LIST_ISEMPTY(&rule->be.expr)) {
7476 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7477 rule->dynamic = 1;
7478 free(pxname);
7479 continue;
7480 }
7481 /* simple string: free the expression and fall back to static rule */
7482 free(node->arg);
7483 free(node);
7484 }
7485
7486 rule->dynamic = 0;
7487 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007488
Willy Tarreauafb39922015-05-26 12:04:09 +02007489 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007490 if (!target) {
7491 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7492 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007493 cfgerr++;
7494 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007495 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7496 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007497 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007498 } else if (target->mode != curproxy->mode &&
7499 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7500
7501 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7502 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7503 curproxy->conf.file, curproxy->conf.line,
7504 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7505 target->conf.file, target->conf.line);
7506 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007507 } else {
7508 free((void *)rule->be.name);
7509 rule->be.backend = target;
7510 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007511 }
7512
Willy Tarreau64ab6072014-09-16 12:17:36 +02007513 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007514 list_for_each_entry(srule, &curproxy->server_rules, list) {
7515 struct server *target = findserver(curproxy, srule->srv.name);
7516
7517 if (!target) {
7518 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7519 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7520 cfgerr++;
7521 continue;
7522 }
7523 free((void *)srule->srv.name);
7524 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007525 }
7526
Emeric Brunb982a3d2010-01-04 15:45:53 +01007527 /* find the target table for 'stick' rules */
7528 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7529 struct proxy *target;
7530
Emeric Brun1d33b292010-01-04 15:47:17 +01007531 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7532 if (mrule->flags & STK_IS_STORE)
7533 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7534
Emeric Brunb982a3d2010-01-04 15:45:53 +01007535 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007536 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007537 else
7538 target = curproxy;
7539
7540 if (!target) {
7541 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7542 curproxy->id, mrule->table.name);
7543 cfgerr++;
7544 }
7545 else if (target->table.size == 0) {
7546 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7547 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7548 cfgerr++;
7549 }
Willy Tarreau12785782012-04-27 21:37:17 +02007550 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7551 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007552 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7553 cfgerr++;
7554 }
7555 else {
7556 free((void *)mrule->table.name);
7557 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007558 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007559 }
7560 }
7561
7562 /* find the target table for 'store response' rules */
7563 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7564 struct proxy *target;
7565
Emeric Brun1d33b292010-01-04 15:47:17 +01007566 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7567
Emeric Brunb982a3d2010-01-04 15:45:53 +01007568 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007569 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007570 else
7571 target = curproxy;
7572
7573 if (!target) {
7574 Alert("Proxy '%s': unable to find store table '%s'.\n",
7575 curproxy->id, mrule->table.name);
7576 cfgerr++;
7577 }
7578 else if (target->table.size == 0) {
7579 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7580 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7581 cfgerr++;
7582 }
Willy Tarreau12785782012-04-27 21:37:17 +02007583 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7584 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007585 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7586 cfgerr++;
7587 }
7588 else {
7589 free((void *)mrule->table.name);
7590 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007591 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007592 }
7593 }
7594
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007595 /* find the target table for 'tcp-request' layer 4 rules */
7596 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7597 struct proxy *target;
7598
Willy Tarreaub4c84932013-07-23 19:15:30 +02007599 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007600 continue;
7601
7602 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007603 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007604 else
7605 target = curproxy;
7606
7607 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007608 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7609 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007610 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007611 cfgerr++;
7612 }
7613 else if (target->table.size == 0) {
7614 Alert("Proxy '%s': table '%s' used but not configured.\n",
7615 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7616 cfgerr++;
7617 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007618 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7619 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7620 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 +01007621 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007622 cfgerr++;
7623 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007624 else {
7625 free(trule->act_prm.trk_ctr.table.n);
7626 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007627 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007628 * to pass a list of counters to track and allocate them right here using
7629 * stktable_alloc_data_type().
7630 */
7631 }
7632 }
7633
Willy Tarreaud1f96522010-08-03 19:34:32 +02007634 /* find the target table for 'tcp-request' layer 6 rules */
7635 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7636 struct proxy *target;
7637
Willy Tarreaub4c84932013-07-23 19:15:30 +02007638 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007639 continue;
7640
7641 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007642 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007643 else
7644 target = curproxy;
7645
7646 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007647 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7648 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007649 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007650 cfgerr++;
7651 }
7652 else if (target->table.size == 0) {
7653 Alert("Proxy '%s': table '%s' used but not configured.\n",
7654 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7655 cfgerr++;
7656 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007657 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7658 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7659 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 +01007660 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007661 cfgerr++;
7662 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007663 else {
7664 free(trule->act_prm.trk_ctr.table.n);
7665 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007666 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007667 * to pass a list of counters to track and allocate them right here using
7668 * stktable_alloc_data_type().
7669 */
7670 }
7671 }
7672
Willy Tarreau09448f72014-06-25 18:12:15 +02007673 /* find the target table for 'http-request' layer 7 rules */
7674 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7675 struct proxy *target;
7676
7677 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7678 continue;
7679
7680 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007681 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007682 else
7683 target = curproxy;
7684
7685 if (!target) {
7686 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7687 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7688 http_req_trk_idx(hrqrule->action));
7689 cfgerr++;
7690 }
7691 else if (target->table.size == 0) {
7692 Alert("Proxy '%s': table '%s' used but not configured.\n",
7693 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7694 cfgerr++;
7695 }
7696 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7697 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7698 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7699 http_req_trk_idx(hrqrule->action));
7700 cfgerr++;
7701 }
7702 else {
7703 free(hrqrule->act_prm.trk_ctr.table.n);
7704 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7705 /* Note: if we decide to enhance the track-sc syntax, we may be able
7706 * to pass a list of counters to track and allocate them right here using
7707 * stktable_alloc_data_type().
7708 */
7709 }
7710 }
7711
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007712 /* move any "block" rules at the beginning of the http-request rules */
7713 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7714 /* insert block_rules into http_req_rules at the beginning */
7715 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7716 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7717 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7718 curproxy->http_req_rules.n = curproxy->block_rules.n;
7719 LIST_INIT(&curproxy->block_rules);
7720 }
7721
Emeric Brun32da3c42010-09-23 18:39:19 +02007722 if (curproxy->table.peers.name) {
7723 struct peers *curpeers = peers;
7724
7725 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7726 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7727 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007728 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007729 break;
7730 }
7731 }
7732
7733 if (!curpeers) {
7734 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7735 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007736 free((void *)curproxy->table.peers.name);
7737 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007738 cfgerr++;
7739 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007740 else if (curpeers->state == PR_STSTOPPED) {
7741 /* silently disable this peers section */
7742 curproxy->table.peers.p = NULL;
7743 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007744 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007745 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7746 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007747 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007748 cfgerr++;
7749 }
7750 }
7751
Simon Horman9dc49962015-01-30 11:22:59 +09007752
7753 if (curproxy->email_alert.mailers.name) {
7754 struct mailers *curmailers = mailers;
7755
7756 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7757 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7758 free(curproxy->email_alert.mailers.name);
7759 curproxy->email_alert.mailers.m = curmailers;
7760 curmailers->users++;
7761 break;
7762 }
7763 }
7764
7765 if (!curmailers) {
7766 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7767 curproxy->id, curproxy->email_alert.mailers.name);
7768 free_email_alert(curproxy);
7769 cfgerr++;
7770 }
7771 }
7772
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007773 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007774 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007775 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7776 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7777 "proxy", curproxy->id);
7778 cfgerr++;
7779 goto out_uri_auth_compat;
7780 }
7781
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007782 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007783 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007784 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007785 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007786
Willy Tarreau95fa4692010-02-01 13:05:50 +01007787 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7788 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007789
7790 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007791 uri_auth_compat_req[i++] = "realm";
7792 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7793 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007794
Willy Tarreau95fa4692010-02-01 13:05:50 +01007795 uri_auth_compat_req[i++] = "unless";
7796 uri_auth_compat_req[i++] = "{";
7797 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7798 uri_auth_compat_req[i++] = "}";
7799 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007800
Willy Tarreauff011f22011-01-06 17:51:27 +01007801 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7802 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007803 cfgerr++;
7804 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007805 }
7806
Willy Tarreauff011f22011-01-06 17:51:27 +01007807 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007808
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007809 if (curproxy->uri_auth->auth_realm) {
7810 free(curproxy->uri_auth->auth_realm);
7811 curproxy->uri_auth->auth_realm = NULL;
7812 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007813
7814 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007815 }
7816out_uri_auth_compat:
7817
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007818 /* compile the log format */
7819 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007820 if (curproxy->conf.logformat_string != default_http_log_format &&
7821 curproxy->conf.logformat_string != default_tcp_log_format &&
7822 curproxy->conf.logformat_string != clf_http_log_format)
7823 free(curproxy->conf.logformat_string);
7824 curproxy->conf.logformat_string = NULL;
7825 free(curproxy->conf.lfs_file);
7826 curproxy->conf.lfs_file = NULL;
7827 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007828 }
7829
Willy Tarreau62a61232013-04-12 18:13:46 +02007830 if (curproxy->conf.logformat_string) {
7831 curproxy->conf.args.ctx = ARGC_LOG;
7832 curproxy->conf.args.file = curproxy->conf.lfs_file;
7833 curproxy->conf.args.line = curproxy->conf.lfs_line;
7834 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007835 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007836 curproxy->conf.args.file = NULL;
7837 curproxy->conf.args.line = 0;
7838 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007839
Willy Tarreau62a61232013-04-12 18:13:46 +02007840 if (curproxy->conf.uniqueid_format_string) {
7841 curproxy->conf.args.ctx = ARGC_UIF;
7842 curproxy->conf.args.file = curproxy->conf.uif_file;
7843 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007844 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007845 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007846 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007847 curproxy->conf.args.file = NULL;
7848 curproxy->conf.args.line = 0;
7849 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007850
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007851 /* only now we can check if some args remain unresolved.
7852 * This must be done after the users and groups resolution.
7853 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007854 cfgerr += smp_resolve_args(curproxy);
7855 if (!cfgerr)
7856 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007857
Willy Tarreau2738a142006-07-08 17:28:09 +02007858 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007859 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007860 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007861 (!curproxy->timeout.connect ||
7862 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007863 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007864 " | While not properly invalid, you will certainly encounter various problems\n"
7865 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007866 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007867 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007868 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007869 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007870
Willy Tarreau1fa31262007-12-03 00:36:16 +01007871 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7872 * We must still support older configurations, so let's find out whether those
7873 * parameters have been set or must be copied from contimeouts.
7874 */
7875 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007876 if (!curproxy->timeout.tarpit ||
7877 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007878 /* tarpit timeout not set. We search in the following order:
7879 * default.tarpit, curr.connect, default.connect.
7880 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007881 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007882 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007883 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007884 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007885 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007886 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007887 }
7888 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007889 (!curproxy->timeout.queue ||
7890 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007891 /* queue timeout not set. We search in the following order:
7892 * default.queue, curr.connect, default.connect.
7893 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007894 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007895 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007896 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007897 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007898 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007899 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007900 }
7901 }
7902
Willy Tarreau1620ec32011-08-06 17:05:02 +02007903 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007904 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7905 curproxy->check_req = (char *)malloc(curproxy->check_len);
7906 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007907 }
7908
Willy Tarreau215663d2014-06-13 18:30:23 +02007909 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7910 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7911 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7912 proxy_type_str(curproxy), curproxy->id);
7913 err_code |= ERR_WARN;
7914 }
7915
Willy Tarreau193b8c62012-11-22 00:17:38 +01007916 /* ensure that cookie capture length is not too large */
7917 if (curproxy->capture_len >= global.tune.cookie_len) {
7918 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7919 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7920 err_code |= ERR_WARN;
7921 curproxy->capture_len = global.tune.cookie_len - 1;
7922 }
7923
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007924 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007925 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007926 curproxy->req_cap_pool = create_pool("ptrcap",
7927 curproxy->nb_req_cap * sizeof(char *),
7928 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007929 }
7930
7931 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007932 curproxy->rsp_cap_pool = create_pool("ptrcap",
7933 curproxy->nb_rsp_cap * sizeof(char *),
7934 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007935 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007936
Willy Tarreaubaaee002006-06-26 02:48:02 +02007937 /* first, we will invert the servers list order */
7938 newsrv = NULL;
7939 while (curproxy->srv) {
7940 struct server *next;
7941
7942 next = curproxy->srv->next;
7943 curproxy->srv->next = newsrv;
7944 newsrv = curproxy->srv;
7945 if (!next)
7946 break;
7947 curproxy->srv = next;
7948 }
7949
Willy Tarreau17edc812014-01-03 12:14:34 +01007950 /* Check that no server name conflicts. This causes trouble in the stats.
7951 * We only emit a warning for the first conflict affecting each server,
7952 * in order to avoid combinatory explosion if all servers have the same
7953 * name. We do that only for servers which do not have an explicit ID,
7954 * because these IDs were made also for distinguishing them and we don't
7955 * want to annoy people who correctly manage them.
7956 */
7957 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7958 struct server *other_srv;
7959
7960 if (newsrv->puid)
7961 continue;
7962
7963 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7964 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7965 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7966 newsrv->conf.file, newsrv->conf.line,
7967 proxy_type_str(curproxy), curproxy->id,
7968 newsrv->id, other_srv->conf.line);
7969 break;
7970 }
7971 }
7972 }
7973
Willy Tarreaudd701652010-05-25 23:03:02 +02007974 /* assign automatic UIDs to servers which don't have one yet */
7975 next_id = 1;
7976 newsrv = curproxy->srv;
7977 while (newsrv != NULL) {
7978 if (!newsrv->puid) {
7979 /* server ID not set, use automatic numbering with first
7980 * spare entry starting with next_svid.
7981 */
7982 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7983 newsrv->conf.id.key = newsrv->puid = next_id;
7984 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7985 }
7986 next_id++;
7987 newsrv = newsrv->next;
7988 }
7989
Willy Tarreau20697042007-11-15 23:26:18 +01007990 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007991 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007992
Willy Tarreau62c3be22012-01-20 13:12:32 +01007993 /*
7994 * If this server supports a maxconn parameter, it needs a dedicated
7995 * tasks to fill the emptied slots when a connection leaves.
7996 * Also, resolve deferred tracking dependency if needed.
7997 */
7998 newsrv = curproxy->srv;
7999 while (newsrv != NULL) {
8000 if (newsrv->minconn > newsrv->maxconn) {
8001 /* Only 'minconn' was specified, or it was higher than or equal
8002 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8003 * this will avoid further useless expensive computations.
8004 */
8005 newsrv->maxconn = newsrv->minconn;
8006 } else if (newsrv->maxconn && !newsrv->minconn) {
8007 /* minconn was not specified, so we set it to maxconn */
8008 newsrv->minconn = newsrv->maxconn;
8009 }
8010
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008011#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008012 if (newsrv->use_ssl || newsrv->check.use_ssl)
8013 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008014#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008015
Willy Tarreau2f075e92013-12-03 11:11:34 +01008016 /* set the check type on the server */
8017 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8018
Willy Tarreau62c3be22012-01-20 13:12:32 +01008019 if (newsrv->trackit) {
8020 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008021 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008022 char *pname, *sname;
8023
8024 pname = newsrv->trackit;
8025 sname = strrchr(pname, '/');
8026
8027 if (sname)
8028 *sname++ = '\0';
8029 else {
8030 sname = pname;
8031 pname = NULL;
8032 }
8033
8034 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008035 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008036 if (!px) {
8037 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8038 proxy_type_str(curproxy), curproxy->id,
8039 newsrv->id, pname);
8040 cfgerr++;
8041 goto next_srv;
8042 }
8043 } else
8044 px = curproxy;
8045
8046 srv = findserver(px, sname);
8047 if (!srv) {
8048 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8049 proxy_type_str(curproxy), curproxy->id,
8050 newsrv->id, sname);
8051 cfgerr++;
8052 goto next_srv;
8053 }
8054
Willy Tarreau32091232014-05-16 13:52:00 +02008055 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8056 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8057 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008058 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008059 "tracking as it does not have any check nor agent enabled.\n",
8060 proxy_type_str(curproxy), curproxy->id,
8061 newsrv->id, px->id, srv->id);
8062 cfgerr++;
8063 goto next_srv;
8064 }
8065
8066 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8067
8068 if (loop) {
8069 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8070 "belongs to a tracking chain looping back to %s/%s.\n",
8071 proxy_type_str(curproxy), curproxy->id,
8072 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008073 cfgerr++;
8074 goto next_srv;
8075 }
8076
8077 if (curproxy != px &&
8078 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8079 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8080 "tracking: disable-on-404 option inconsistency.\n",
8081 proxy_type_str(curproxy), curproxy->id,
8082 newsrv->id, px->id, srv->id);
8083 cfgerr++;
8084 goto next_srv;
8085 }
8086
8087 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008088 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008089 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008090 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008091 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008092 }
8093
8094 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008095 newsrv->tracknext = srv->trackers;
8096 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008097
8098 free(newsrv->trackit);
8099 newsrv->trackit = NULL;
8100 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008101
8102 /*
8103 * resolve server's resolvers name and update the resolvers pointer
8104 * accordingly
8105 */
8106 if (newsrv->resolvers_id) {
8107 struct dns_resolvers *curr_resolvers;
8108 int found;
8109
8110 found = 0;
8111 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8112 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8113 found = 1;
8114 break;
8115 }
8116 }
8117
8118 if (!found) {
8119 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8120 proxy_type_str(curproxy), curproxy->id,
8121 newsrv->id, newsrv->resolvers_id);
8122 cfgerr++;
8123 } else {
8124 free(newsrv->resolvers_id);
8125 newsrv->resolvers_id = NULL;
8126 if (newsrv->resolution)
8127 newsrv->resolution->resolvers = curr_resolvers;
8128 }
8129 }
8130 else {
8131 /* if no resolvers section associated to this server
8132 * we can clean up the associated resolution structure
8133 */
8134 if (newsrv->resolution) {
8135 free(newsrv->resolution->hostname_dn);
8136 newsrv->resolution->hostname_dn = NULL;
8137 free(newsrv->resolution);
8138 newsrv->resolution = NULL;
8139 }
8140 }
8141
Willy Tarreau62c3be22012-01-20 13:12:32 +01008142 next_srv:
8143 newsrv = newsrv->next;
8144 }
8145
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008146 /* We have to initialize the server lookup mechanism depending
8147 * on what LB algorithm was choosen.
8148 */
8149
8150 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8151 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8152 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008153 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8154 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8155 init_server_map(curproxy);
8156 } else {
8157 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8158 fwrr_init_server_groups(curproxy);
8159 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008160 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008161
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008162 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008163 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8164 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8165 fwlc_init_server_tree(curproxy);
8166 } else {
8167 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8168 fas_init_server_tree(curproxy);
8169 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008170 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008171
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008172 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008173 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8174 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8175 chash_init_server_tree(curproxy);
8176 } else {
8177 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8178 init_server_map(curproxy);
8179 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008180 break;
8181 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008182
8183 if (curproxy->options & PR_O_LOGASAP)
8184 curproxy->to_log &= ~LW_BYTES;
8185
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008186 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01008187 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008188 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8189 proxy_type_str(curproxy), curproxy->id);
8190 err_code |= ERR_WARN;
8191 }
8192
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008193 if (curproxy->mode != PR_MODE_HTTP) {
8194 int optnum;
8195
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008196 if (curproxy->uri_auth) {
8197 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8198 proxy_type_str(curproxy), curproxy->id);
8199 err_code |= ERR_WARN;
8200 curproxy->uri_auth = NULL;
8201 }
8202
Willy Tarreau87cf5142011-08-19 22:57:24 +02008203 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008204 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8205 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8206 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008207 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008208 }
8209
8210 if (curproxy->options & PR_O_ORGTO) {
8211 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8212 "originalto", proxy_type_str(curproxy), curproxy->id);
8213 err_code |= ERR_WARN;
8214 curproxy->options &= ~PR_O_ORGTO;
8215 }
8216
8217 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8218 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8219 (curproxy->cap & cfg_opts[optnum].cap) &&
8220 (curproxy->options & cfg_opts[optnum].val)) {
8221 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8222 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8223 err_code |= ERR_WARN;
8224 curproxy->options &= ~cfg_opts[optnum].val;
8225 }
8226 }
8227
8228 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8229 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8230 (curproxy->cap & cfg_opts2[optnum].cap) &&
8231 (curproxy->options2 & cfg_opts2[optnum].val)) {
8232 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8233 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8234 err_code |= ERR_WARN;
8235 curproxy->options2 &= ~cfg_opts2[optnum].val;
8236 }
8237 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008238
Pieter Baauwd551fb52013-05-08 22:49:23 +02008239#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008240 if (curproxy->conn_src.bind_hdr_occ) {
8241 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008242 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008243 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008244 err_code |= ERR_WARN;
8245 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008246#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008247 }
8248
Willy Tarreaubaaee002006-06-26 02:48:02 +02008249 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008250 * ensure that we're not cross-dressing a TCP server into HTTP.
8251 */
8252 newsrv = curproxy->srv;
8253 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008254 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008255 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8256 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008257 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008258 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008259
Willy Tarreau0cec3312011-10-31 13:49:26 +01008260 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8261 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8262 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8263 err_code |= ERR_WARN;
8264 }
8265
Willy Tarreauc93cd162014-05-13 15:54:22 +02008266 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008267 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8268 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8269 err_code |= ERR_WARN;
8270 }
8271
Pieter Baauwd551fb52013-05-08 22:49:23 +02008272#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008273 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8274 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008275 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 +01008276 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008277 err_code |= ERR_WARN;
8278 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008279#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008280 newsrv = newsrv->next;
8281 }
8282
Willy Tarreaue42bd962014-09-16 16:21:19 +02008283 /* check if we have a frontend with "tcp-request content" looking at L7
8284 * with no inspect-delay
8285 */
8286 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8287 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
8288 if (trule->action == TCP_ACT_CAPTURE &&
8289 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8290 break;
8291 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
8292 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8293 break;
8294 }
8295
8296 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8297 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8298 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8299 " This means that these rules will randomly find their contents. This can be fixed by"
8300 " setting the tcp-request inspect-delay.\n",
8301 proxy_type_str(curproxy), curproxy->id);
8302 err_code |= ERR_WARN;
8303 }
8304 }
8305
Willy Tarreauc1a21672009-08-16 22:37:44 +02008306 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008307 if (!curproxy->accept)
8308 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008309
Willy Tarreauc1a21672009-08-16 22:37:44 +02008310 if (curproxy->tcp_req.inspect_delay ||
8311 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008312 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008313
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008314 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008315 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008316 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008317 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008318
8319 /* both TCP and HTTP must check switching rules */
8320 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8321 }
8322
8323 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008324 if (curproxy->tcp_req.inspect_delay ||
8325 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8326 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8327
Emeric Brun97679e72010-09-23 17:56:44 +02008328 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8329 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8330
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008331 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008332 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008333 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008334 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008335
8336 /* If the backend does requires RDP cookie persistence, we have to
8337 * enable the corresponding analyser.
8338 */
8339 if (curproxy->options2 & PR_O2_RDPC_PRST)
8340 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8341 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008342 }
8343
8344 /***********************************************************/
8345 /* At this point, target names have already been resolved. */
8346 /***********************************************************/
8347
8348 /* Check multi-process mode compatibility */
8349
8350 if (global.nbproc > 1 && global.stats_fe) {
8351 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8352 unsigned long mask;
8353
8354 mask = nbits(global.nbproc);
8355 if (global.stats_fe->bind_proc)
8356 mask &= global.stats_fe->bind_proc;
8357
8358 if (bind_conf->bind_proc)
8359 mask &= bind_conf->bind_proc;
8360
8361 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008362 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008363 break;
8364 }
8365 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8366 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");
8367 }
8368 }
8369
8370 /* Make each frontend inherit bind-process from its listeners when not specified. */
8371 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8372 if (curproxy->bind_proc)
8373 continue;
8374
8375 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8376 unsigned long mask;
8377
Willy Tarreaue428b082015-05-04 21:57:58 +02008378 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008379 curproxy->bind_proc |= mask;
8380 }
8381
8382 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008383 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008384 }
8385
8386 if (global.stats_fe) {
8387 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8388 unsigned long mask;
8389
Willy Tarreaue428b082015-05-04 21:57:58 +02008390 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008391 global.stats_fe->bind_proc |= mask;
8392 }
8393 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008394 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008395 }
8396
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008397 /* propagate bindings from frontends to backends. Don't do it if there
8398 * are any fatal errors as we must not call it with unresolved proxies.
8399 */
8400 if (!cfgerr) {
8401 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8402 if (curproxy->cap & PR_CAP_FE)
8403 propagate_processes(curproxy, NULL);
8404 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008405 }
8406
8407 /* Bind each unbound backend to all processes when not specified. */
8408 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8409 if (curproxy->bind_proc)
8410 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008411 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008412 }
8413
8414 /*******************************************************/
8415 /* At this step, all proxies have a non-null bind_proc */
8416 /*******************************************************/
8417
8418 /* perform the final checks before creating tasks */
8419
8420 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8421 struct listener *listener;
8422 unsigned int next_id;
8423 int nbproc;
8424
David Carliere6c39412015-07-02 07:00:17 +00008425 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008426
Emeric Brunc52962f2012-11-15 18:28:02 +01008427#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008428 /* Configure SSL for each bind line.
8429 * Note: if configuration fails at some point, the ->ctx member
8430 * remains NULL so that listeners can later detach.
8431 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008432 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008433 int alloc_ctx;
8434
Emeric Brunc52962f2012-11-15 18:28:02 +01008435 if (!bind_conf->is_ssl) {
8436 if (bind_conf->default_ctx) {
8437 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8438 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8439 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008440 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008441 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008442 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008443 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008444 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008445 cfgerr++;
8446 continue;
8447 }
8448
Emeric Brun8dc60392014-05-09 13:52:00 +02008449 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008450 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008451 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8452 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");
8453 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008454 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008455 cfgerr++;
8456 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008457 }
8458
Emeric Brunfc0421f2012-09-07 17:30:07 +02008459 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008460 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008461
8462 /* initialize CA variables if the certificates generation is enabled */
8463 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008464 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008465#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008466
Willy Tarreaue6b98942007-10-29 01:09:36 +01008467 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008468 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008469 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008470 if (!listener->luid) {
8471 /* listener ID not set, use automatic numbering with first
8472 * spare entry starting with next_luid.
8473 */
8474 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8475 listener->conf.id.key = listener->luid = next_id;
8476 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008477 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008478 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008479
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008480 /* enable separate counters */
8481 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8482 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008483 if (!listener->name)
8484 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008485 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008486
Willy Tarreaue6b98942007-10-29 01:09:36 +01008487 if (curproxy->options & PR_O_TCP_NOLING)
8488 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008489 if (!listener->maxconn)
8490 listener->maxconn = curproxy->maxconn;
8491 if (!listener->backlog)
8492 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008493 if (!listener->maxaccept)
8494 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8495
8496 /* we want to have an optimal behaviour on single process mode to
8497 * maximize the work at once, but in multi-process we want to keep
8498 * some fairness between processes, so we target half of the max
8499 * number of events to be balanced over all the processes the proxy
8500 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8501 * used to disable the limit.
8502 */
8503 if (listener->maxaccept > 0) {
8504 if (nbproc > 1)
8505 listener->maxaccept = (listener->maxaccept + 1) / 2;
8506 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8507 }
8508
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008509 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008510 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008511 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008512 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008513
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008514 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8515 listener->options |= LI_O_TCP_RULES;
8516
Willy Tarreaude3041d2010-05-31 10:56:17 +02008517 if (curproxy->mon_mask.s_addr)
8518 listener->options |= LI_O_CHK_MONNET;
8519
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008520 /* smart accept mode is automatic in HTTP mode */
8521 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008522 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008523 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8524 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008525 }
8526
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008527 /* Release unused SSL configs */
8528 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8529 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008530 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008531#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008532 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008533 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008534 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008535 free(bind_conf->ca_sign_file);
8536 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008537 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008538 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008539 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008540 if(bind_conf->keys_ref) {
8541 free(bind_conf->keys_ref->filename);
8542 free(bind_conf->keys_ref->tlskeys);
8543 free(bind_conf->keys_ref);
8544 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008545#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008546 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008547
Willy Tarreau102df612014-05-07 23:56:38 +02008548 if (nbproc > 1) {
8549 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008550 int count, maxproc = 0;
8551
8552 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008553 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008554 if (count > maxproc)
8555 maxproc = count;
8556 }
8557 /* backends have 0, frontends have 1 or more */
8558 if (maxproc != 1)
8559 Warning("Proxy '%s': in multi-process mode, stats will be"
8560 " limited to process assigned to the current request.\n",
8561 curproxy->id);
8562
Willy Tarreau102df612014-05-07 23:56:38 +02008563 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8564 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8565 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008566 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008567 }
Willy Tarreau102df612014-05-07 23:56:38 +02008568 if (curproxy->appsession_name) {
8569 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8570 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008571 }
Willy Tarreau102df612014-05-07 23:56:38 +02008572 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8573 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8574 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008575 }
8576 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008577
8578 /* create the task associated with the proxy */
8579 curproxy->task = task_new();
8580 if (curproxy->task) {
8581 curproxy->task->context = curproxy;
8582 curproxy->task->process = manage_proxy;
8583 /* no need to queue, it will be done automatically if some
8584 * listener gets limited.
8585 */
8586 curproxy->task->expire = TICK_ETERNITY;
8587 } else {
8588 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8589 curproxy->id);
8590 cfgerr++;
8591 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008592 }
8593
Willy Tarreaufbb78422011-06-05 15:38:35 +02008594 /* automatically compute fullconn if not set. We must not do it in the
8595 * loop above because cross-references are not yet fully resolved.
8596 */
8597 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8598 /* If <fullconn> is not set, let's set it to 10% of the sum of
8599 * the possible incoming frontend's maxconns.
8600 */
8601 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8602 struct proxy *fe;
8603 int total = 0;
8604
8605 /* sum up the number of maxconns of frontends which
8606 * reference this backend at least once or which are
8607 * the same one ('listen').
8608 */
8609 for (fe = proxy; fe; fe = fe->next) {
8610 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008611 int found = 0;
8612
8613 if (!(fe->cap & PR_CAP_FE))
8614 continue;
8615
8616 if (fe == curproxy) /* we're on a "listen" instance */
8617 found = 1;
8618
8619 if (fe->defbe.be == curproxy) /* "default_backend" */
8620 found = 1;
8621
8622 /* check if a "use_backend" rule matches */
8623 if (!found) {
8624 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008625 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008626 found = 1;
8627 break;
8628 }
8629 }
8630 }
8631
Willy Tarreaufbb78422011-06-05 15:38:35 +02008632 /* now we've checked all possible ways to reference a backend
8633 * from a frontend.
8634 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008635 if (!found)
8636 continue;
8637 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008638 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008639 /* we have the sum of the maxconns in <total>. We only
8640 * keep 10% of that sum to set the default fullconn, with
8641 * a hard minimum of 1 (to avoid a divide by zero).
8642 */
8643 curproxy->fullconn = (total + 9) / 10;
8644 if (!curproxy->fullconn)
8645 curproxy->fullconn = 1;
8646 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008647 }
8648
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008649 /*
8650 * Recount currently required checks.
8651 */
8652
8653 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8654 int optnum;
8655
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008656 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8657 if (curproxy->options & cfg_opts[optnum].val)
8658 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008659
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008660 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8661 if (curproxy->options2 & cfg_opts2[optnum].val)
8662 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008663 }
8664
Willy Tarreau0fca4832015-05-01 19:12:05 +02008665 /* compute the required process bindings for the peers */
8666 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8667 if (curproxy->table.peers.p)
8668 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8669
Willy Tarreau122541c2011-09-07 21:24:49 +02008670 if (peers) {
8671 struct peers *curpeers = peers, **last;
8672 struct peer *p, *pb;
8673
Willy Tarreau1e273012015-05-01 19:15:17 +02008674 /* Remove all peers sections which don't have a valid listener,
8675 * which are not used by any table, or which are bound to more
8676 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008677 */
8678 last = &peers;
8679 while (*last) {
8680 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008681
8682 if (curpeers->state == PR_STSTOPPED) {
8683 /* the "disabled" keyword was present */
8684 if (curpeers->peers_fe)
8685 stop_proxy(curpeers->peers_fe);
8686 curpeers->peers_fe = NULL;
8687 }
8688 else if (!curpeers->peers_fe) {
8689 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8690 curpeers->id, localpeer);
8691 }
David Carliere6c39412015-07-02 07:00:17 +00008692 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008693 /* either it's totally stopped or too much used */
8694 if (curpeers->peers_fe->bind_proc) {
8695 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008696 "running in different processes (%d different ones). "
8697 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008698 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008699 cfgerr++;
8700 }
8701 stop_proxy(curpeers->peers_fe);
8702 curpeers->peers_fe = NULL;
8703 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008704 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008705 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008706 last = &curpeers->next;
8707 continue;
8708 }
8709
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008710 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008711 p = curpeers->remote;
8712 while (p) {
8713 pb = p->next;
8714 free(p->id);
8715 free(p);
8716 p = pb;
8717 }
8718
8719 /* Destroy and unlink this curpeers section.
8720 * Note: curpeers is backed up into *last.
8721 */
8722 free(curpeers->id);
8723 curpeers = curpeers->next;
8724 free(*last);
8725 *last = curpeers;
8726 }
8727 }
8728
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008729 /* initialize stick-tables on backend capable proxies. This must not
8730 * be done earlier because the data size may be discovered while parsing
8731 * other proxies.
8732 */
8733 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8734 if (curproxy->state == PR_STSTOPPED)
8735 continue;
8736
8737 if (!stktable_init(&curproxy->table)) {
8738 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8739 cfgerr++;
8740 }
8741 }
8742
Simon Horman0d16a402015-01-30 11:22:58 +09008743 if (mailers) {
8744 struct mailers *curmailers = mailers, **last;
8745 struct mailer *m, *mb;
8746
8747 /* Remove all mailers sections which don't have a valid listener.
8748 * This can happen when a mailers section is never referenced.
8749 */
8750 last = &mailers;
8751 while (*last) {
8752 curmailers = *last;
8753 if (curmailers->users) {
8754 last = &curmailers->next;
8755 continue;
8756 }
8757
8758 Warning("Removing incomplete section 'mailers %s'.\n",
8759 curmailers->id);
8760
8761 m = curmailers->mailer_list;
8762 while (m) {
8763 mb = m->next;
8764 free(m->id);
8765 free(m);
8766 m = mb;
8767 }
8768
8769 /* Destroy and unlink this curmailers section.
8770 * Note: curmailers is backed up into *last.
8771 */
8772 free(curmailers->id);
8773 curmailers = curmailers->next;
8774 free(*last);
8775 *last = curmailers;
8776 }
8777 }
8778
Willy Tarreau34eb6712011-10-24 18:15:04 +02008779 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008780 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008781 MEM_F_SHARED);
8782
Willy Tarreaubb925012009-07-23 13:36:36 +02008783 if (cfgerr > 0)
8784 err_code |= ERR_ALERT | ERR_FATAL;
8785 out:
8786 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008787}
8788
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008789/*
8790 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8791 * parsing sessions.
8792 */
8793void cfg_register_keywords(struct cfg_kw_list *kwl)
8794{
8795 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8796}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008797
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008798/*
8799 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8800 */
8801void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8802{
8803 LIST_DEL(&kwl->list);
8804 LIST_INIT(&kwl->list);
8805}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008806
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008807/* this function register new section in the haproxy configuration file.
8808 * <section_name> is the name of this new section and <section_parser>
8809 * is the called parser. If two section declaration have the same name,
8810 * only the first declared is used.
8811 */
8812int cfg_register_section(char *section_name,
8813 int (*section_parser)(const char *, int, char **, int))
8814{
8815 struct cfg_section *cs;
8816
8817 cs = calloc(1, sizeof(*cs));
8818 if (!cs) {
8819 Alert("register section '%s': out of memory.\n", section_name);
8820 return 0;
8821 }
8822
8823 cs->section_name = section_name;
8824 cs->section_parser = section_parser;
8825
8826 LIST_ADDQ(&sections, &cs->list);
8827
8828 return 1;
8829}
8830
Willy Tarreaubaaee002006-06-26 02:48:02 +02008831/*
8832 * Local variables:
8833 * c-indent-level: 8
8834 * c-basic-offset: 8
8835 * End:
8836 */