blob: 3bfacade834a082c96269584338b0f6642442098 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Configuration parser
3 *
Willy Tarreauff011f22011-01-06 17:51:27 +01004 * Copyright 2000-2011 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Cyril Bonté1a0191d2014-08-29 20:20:02 +020013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
22
Willy Tarreaubaaee002006-06-26 02:48:02 +020023#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <netdb.h>
27#include <ctype.h>
Willy Tarreau95c20ac2007-03-25 15:39:23 +020028#include <pwd.h>
29#include <grp.h>
Willy Tarreau0b4ed902007-03-26 00:18:40 +020030#include <errno.h>
Willy Tarreau3f49b302007-06-11 00:29:26 +020031#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <unistd.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020035
Willy Tarreau2dd0d472006-06-29 17:53:05 +020036#include <common/cfgparse.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020037#include <common/chunk.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020038#include <common/config.h>
Willy Tarreau058e9072009-07-20 09:30:05 +020039#include <common/errors.h>
Willy Tarreau2dd0d472006-06-29 17:53:05 +020040#include <common/memory.h>
41#include <common/standard.h>
42#include <common/time.h>
43#include <common/uri_auth.h>
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +010044#include <common/namespace.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
46#include <types/capture.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020047#include <types/compression.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020048#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010049#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020050#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090051#include <types/mailers.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020052
Willy Tarreaueb0c6142007-05-07 00:53:22 +020053#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010054#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020055#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020056#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020058#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020059#include <proto/dumpstats.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020060#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020061#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020062#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010063#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020064#include <proto/lb_fwlc.h>
65#include <proto/lb_fwrr.h>
66#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020067#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020068#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020069#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010070#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020071#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010072#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010073#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020074#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020075#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020076#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020077#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020078#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020079#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010081#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020082
Emeric Brunfc0421f2012-09-07 17:30:07 +020083#ifdef USE_OPENSSL
84#include <types/ssl_sock.h>
85#include <proto/ssl_sock.h>
86#include <proto/shctx.h>
87#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020088
Willy Tarreauf3c69202006-07-09 16:42:34 +020089/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
90 * ssl-hello-chk option to ensure that the remote server speaks SSL.
91 *
92 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
93 */
94const char sslv3_client_hello_pkt[] = {
95 "\x16" /* ContentType : 0x16 = Hanshake */
96 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
97 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
98 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
99 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
100 "\x03\x00" /* Hello Version : 0x0300 = v3 */
101 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
102 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
103 "\x00" /* Session ID length : empty (no session ID) */
104 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
105 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
106 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
107 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
108 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
109 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
110 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
111 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
112 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
113 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
114 "\x00\x38" "\x00\x39" "\x00\x3A"
115 "\x01" /* Compression Length : 0x01 = 1 byte for types */
116 "\x00" /* Compression Type : 0x00 = NULL compression */
117};
118
Willy Tarreau3842f002009-06-14 11:39:52 +0200119/* various keyword modifiers */
120enum kw_mod {
121 KWM_STD = 0, /* normal */
122 KWM_NO, /* "no" prefixed before the keyword */
123 KWM_DEF, /* "default" prefixed before the keyword */
124};
125
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100126/* permit to store configuration section */
127struct cfg_section {
128 struct list list;
129 char *section_name;
130 int (*section_parser)(const char *, int, char **, int);
131};
132
133/* Used to chain configuration sections definitions. This list
134 * stores struct cfg_section
135 */
136struct list sections = LIST_HEAD_INIT(sections);
137
Willy Tarreau13943ab2006-12-31 00:24:10 +0100138/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100139struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100140 const char *name;
141 unsigned int val;
142 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100143 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100144 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100145};
146
147/* proxy->options */
148static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100149{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100150 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
151 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
152 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
153 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
154 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
155 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100156 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200157 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200158 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100159 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100160 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
161 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
162 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100164#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100165 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100166#else
167 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100168#endif
169
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100170 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100171};
172
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100173/* proxy->options2 */
174static const struct cfg_opt cfg_opts2[] =
175{
176#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100177 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
178 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
179 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100180#else
181 { "splice-request", 0, 0, 0, 0 },
182 { "splice-response", 0, 0, 0, 0 },
183 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100184#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100185 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
186 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
187 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
188 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
189 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
190 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
191 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
192 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
193 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400194 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100195 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200196 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200197 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100198 { NULL, 0, 0, 0 }
199};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200200
Willy Tarreau6daf3432008-01-22 16:44:08 +0100201static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
203int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100204int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200206/* List head of all known configuration keywords */
207static struct cfg_kw_list cfg_keywords = {
208 .list = LIST_HEAD_INIT(cfg_keywords.list)
209};
210
Willy Tarreaubaaee002006-06-26 02:48:02 +0200211/*
212 * converts <str> to a list of listeners which are dynamically allocated.
213 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
214 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
215 * - <port> is a numerical port from 1 to 65535 ;
216 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
217 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200218 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
219 * not NULL, it must be a valid pointer to either NULL or a freeable area that
220 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200221 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200222int 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 +0200223{
224 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100225 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200226 int port, end;
227
228 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200229
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100231 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100232 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233
234 str = next;
235 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100236 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200237 *next++ = 0;
238 }
239
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100240 ss2 = str2sa_range(str, &port, &end, err,
241 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix);
242 if (!ss2)
243 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200244
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100245 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100246 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200247 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100248 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200249 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200250
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100251 if (!port || !end) {
252 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
253 goto fail;
254 }
255
Emeric Bruned760922010-10-22 17:59:25 +0200256 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200257 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200258 goto fail;
259 }
260
261 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200262 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200263 goto fail;
264 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200265 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100266 else if (ss2->ss_family == AF_UNSPEC) {
267 socklen_t addr_len;
268
269 /* We want to attach to an already bound fd whose number
270 * is in the addr part of ss2 when cast to sockaddr_in.
271 * Note that by definition there is a single listener.
272 * We still have to determine the address family to
273 * register the correct protocol.
274 */
275 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
276 addr_len = sizeof(*ss2);
277 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
278 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
279 goto fail;
280 }
281
282 port = end = get_host_port(ss2);
283 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200284
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100285 /* OK the address looks correct */
286 ss = *ss2;
287
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288 for (; port <= end; port++) {
289 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100290 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200291 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
292 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
293 l->frontend = curproxy;
294 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200295
Willy Tarreau40aa0702013-03-10 23:51:38 +0100296 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200297 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200298 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100299 l->state = LI_INIT;
300
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100301 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200302 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 tcpv4_add_listener(l);
304 }
Emeric Bruned760922010-10-22 17:59:25 +0200305 else if (ss.ss_family == AF_INET6) {
306 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
307 tcpv6_add_listener(l);
308 }
309 else {
Emeric Bruned760922010-10-22 17:59:25 +0200310 uxst_add_listener(l);
311 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200312
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200313 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100314 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200315 } /* end for(port) */
316 } /* end while(next) */
317 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200318 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 fail:
320 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200321 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200322}
323
William Lallemand6e62fb62015-04-28 16:55:23 +0200324/*
325 * Report a fatal Alert when there is too much arguments
326 * The index is the current keyword in args
327 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
328 * Fill err_code with an ERR_ALERT and an ERR_FATAL
329 */
330int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
331{
332 char *kw = NULL;
333 int i;
334
335 if (!*args[index + maxarg + 1])
336 return 0;
337
338 memprintf(&kw, "%s", args[0]);
339 for (i = 1; i <= index; i++) {
340 memprintf(&kw, "%s %s", kw, args[i]);
341 }
342
343 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
344 free(kw);
345 *err_code |= ERR_ALERT | ERR_FATAL;
346 return 1;
347}
348
349/*
350 * same as alertif_too_many_args_idx with a 0 index
351 */
352int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
353{
354 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
355}
356
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200357/* Report a warning if a rule is placed after a 'tcp-request content' rule.
358 * Return 1 if the warning has been emitted, otherwise 0.
359 */
360int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
361{
362 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
363 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
364 file, line, arg);
365 return 1;
366 }
367 return 0;
368}
369
Willy Tarreau61d18892009-03-31 10:49:21 +0200370/* Report a warning if a rule is placed after a 'block' rule.
371 * Return 1 if the warning has been emitted, otherwise 0.
372 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100373int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200374{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200375 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200376 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
377 file, line, arg);
378 return 1;
379 }
380 return 0;
381}
382
Willy Tarreau5002f572014-04-23 01:32:02 +0200383/* Report a warning if a rule is placed after an 'http_request' rule.
384 * Return 1 if the warning has been emitted, otherwise 0.
385 */
386int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
387{
388 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
389 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
390 file, line, arg);
391 return 1;
392 }
393 return 0;
394}
395
Willy Tarreau61d18892009-03-31 10:49:21 +0200396/* Report a warning if a rule is placed after a reqrewrite rule.
397 * Return 1 if the warning has been emitted, otherwise 0.
398 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100399int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200400{
401 if (proxy->req_exp) {
402 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
403 file, line, arg);
404 return 1;
405 }
406 return 0;
407}
408
409/* Report a warning if a rule is placed after a reqadd rule.
410 * Return 1 if the warning has been emitted, otherwise 0.
411 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100412int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200413{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100414 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200415 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
416 file, line, arg);
417 return 1;
418 }
419 return 0;
420}
421
422/* Report a warning if a rule is placed after a redirect rule.
423 * Return 1 if the warning has been emitted, otherwise 0.
424 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100425int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200426{
427 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
428 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
429 file, line, arg);
430 return 1;
431 }
432 return 0;
433}
434
435/* Report a warning if a rule is placed after a 'use_backend' rule.
436 * Return 1 if the warning has been emitted, otherwise 0.
437 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100438int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200439{
440 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
441 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
442 file, line, arg);
443 return 1;
444 }
445 return 0;
446}
447
Willy Tarreauee445d92014-04-23 01:39:04 +0200448/* Report a warning if a rule is placed after a 'use-server' rule.
449 * Return 1 if the warning has been emitted, otherwise 0.
450 */
451int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
452{
453 if (!LIST_ISEMPTY(&proxy->server_rules)) {
454 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
455 file, line, arg);
456 return 1;
457 }
458 return 0;
459}
460
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200461/* report a warning if a "tcp request connection" rule is dangerously placed */
462int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
463{
464 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
465 warnif_rule_after_block(proxy, file, line, arg) ||
466 warnif_rule_after_http_req(proxy, file, line, arg) ||
467 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
468 warnif_rule_after_reqadd(proxy, file, line, arg) ||
469 warnif_rule_after_redirect(proxy, file, line, arg) ||
470 warnif_rule_after_use_backend(proxy, file, line, arg) ||
471 warnif_rule_after_use_server(proxy, file, line, arg);
472}
473
474/* report a warning if a "tcp request content" rule is dangerously placed */
475int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
476{
477 return warnif_rule_after_block(proxy, file, line, arg) ||
478 warnif_rule_after_http_req(proxy, file, line, arg) ||
479 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
480 warnif_rule_after_reqadd(proxy, file, line, arg) ||
481 warnif_rule_after_redirect(proxy, file, line, arg) ||
482 warnif_rule_after_use_backend(proxy, file, line, arg) ||
483 warnif_rule_after_use_server(proxy, file, line, arg);
484}
485
Willy Tarreau61d18892009-03-31 10:49:21 +0200486/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100487int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200488{
Willy Tarreau5002f572014-04-23 01:32:02 +0200489 return warnif_rule_after_http_req(proxy, file, line, arg) ||
490 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
491 warnif_rule_after_reqadd(proxy, file, line, arg) ||
492 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200493 warnif_rule_after_use_backend(proxy, file, line, arg) ||
494 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200495}
496
497/* report a warning if an http-request rule is dangerously placed */
498int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
499{
Willy Tarreau61d18892009-03-31 10:49:21 +0200500 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
501 warnif_rule_after_reqadd(proxy, file, line, arg) ||
502 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200503 warnif_rule_after_use_backend(proxy, file, line, arg) ||
504 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200505}
506
507/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100508int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200509{
510 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
511 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200512 warnif_rule_after_use_backend(proxy, file, line, arg) ||
513 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200514}
515
516/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100517int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200518{
519 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200520 warnif_rule_after_use_backend(proxy, file, line, arg) ||
521 warnif_rule_after_use_server(proxy, file, line, arg);
522}
523
524/* report a warning if a redirect rule is dangerously placed */
525int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
526{
527 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
528 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200529}
530
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100531/* Report it if a request ACL condition uses some keywords that are incompatible
532 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
533 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
534 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100535 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100536static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100537{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100538 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200539 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100540
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100541 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100542 return 0;
543
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100544 acl = acl_cond_conflicts(cond, where);
545 if (acl) {
546 if (acl->name && *acl->name)
547 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
548 file, line, acl->name, sample_ckp_names(where));
549 else
550 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 +0200551 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100552 return ERR_WARN;
553 }
554 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100555 return 0;
556
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100557 if (acl->name && *acl->name)
558 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200559 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100560 else
561 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200562 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100563 return ERR_WARN;
564}
565
Willy Tarreaubaaee002006-06-26 02:48:02 +0200566/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200567 * parse a line in a <global> section. Returns the error code, 0 if OK, or
568 * any combination of :
569 * - ERR_ABORT: must abort ASAP
570 * - ERR_FATAL: we can continue parsing but not start the service
571 * - ERR_WARN: a warning has been emitted
572 * - ERR_ALERT: an alert has been emitted
573 * Only the two first ones can stop processing, the two others are just
574 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200575 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200576int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200577{
Willy Tarreau058e9072009-07-20 09:30:05 +0200578 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200579 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200580
581 if (!strcmp(args[0], "global")) { /* new section */
582 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200583 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200584 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200585 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200586 else if (!strcmp(args[0], "ca-base")) {
587#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200588 if(alertif_too_many_args(1, file, linenum, args, &err_code))
589 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 if (global.ca_base != NULL) {
591 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
592 err_code |= ERR_ALERT;
593 goto out;
594 }
595 if (*(args[1]) == 0) {
596 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
597 err_code |= ERR_ALERT | ERR_FATAL;
598 goto out;
599 }
600 global.ca_base = strdup(args[1]);
601#else
602 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
603 err_code |= ERR_ALERT | ERR_FATAL;
604 goto out;
605#endif
606 }
607 else if (!strcmp(args[0], "crt-base")) {
608#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200609 if (alertif_too_many_args(1, file, linenum, args, &err_code))
610 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200611 if (global.crt_base != NULL) {
612 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
613 err_code |= ERR_ALERT;
614 goto out;
615 }
616 if (*(args[1]) == 0) {
617 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
618 err_code |= ERR_ALERT | ERR_FATAL;
619 goto out;
620 }
621 global.crt_base = strdup(args[1]);
622#else
623 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
624 err_code |= ERR_ALERT | ERR_FATAL;
625 goto out;
626#endif
627 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200628 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200629 if (alertif_too_many_args(0, file, linenum, args, &err_code))
630 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200631 global.mode |= MODE_DAEMON;
632 }
633 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200634 if (alertif_too_many_args(0, file, linenum, args, &err_code))
635 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200636 global.mode |= MODE_DEBUG;
637 }
638 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(0, file, linenum, args, &err_code))
640 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100641 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200642 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200643 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200644 if (alertif_too_many_args(0, file, linenum, args, &err_code))
645 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100646 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200648 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200649 if (alertif_too_many_args(0, file, linenum, args, &err_code))
650 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100651 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100653 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200654 if (alertif_too_many_args(0, file, linenum, args, &err_code))
655 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100656 global.tune.options &= ~GTUNE_USE_SPLICE;
657 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200658 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200661 global.tune.options &= ~GTUNE_USE_GAI;
662 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200663 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 global.mode |= MODE_QUIET;
667 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200668 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(1, file, linenum, args, &err_code))
670 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200671 if (global.tune.maxpollevents != 0) {
672 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200673 err_code |= ERR_ALERT;
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 }
676 if (*(args[1]) == 0) {
677 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200678 err_code |= ERR_ALERT | ERR_FATAL;
679 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200680 }
681 global.tune.maxpollevents = atol(args[1]);
682 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100683 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200684 if (alertif_too_many_args(1, file, linenum, args, &err_code))
685 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100686 if (global.tune.maxaccept != 0) {
687 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200688 err_code |= ERR_ALERT;
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 }
691 if (*(args[1]) == 0) {
692 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200693 err_code |= ERR_ALERT | ERR_FATAL;
694 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100695 }
696 global.tune.maxaccept = atol(args[1]);
697 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200698 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200699 if (alertif_too_many_args(1, file, linenum, args, &err_code))
700 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200701 if (*(args[1]) == 0) {
702 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
703 err_code |= ERR_ALERT | ERR_FATAL;
704 goto out;
705 }
706 global.tune.chksize = atol(args[1]);
707 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200708#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200709 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200710 if (alertif_too_many_args(0, file, linenum, args, &err_code))
711 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200712 global.tune.sslprivatecache = 1;
713 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100714 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200715 if (alertif_too_many_args(1, file, linenum, args, &err_code))
716 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200717 if (*(args[1]) == 0) {
718 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
719 err_code |= ERR_ALERT | ERR_FATAL;
720 goto out;
721 }
722 global.tune.sslcachesize = atol(args[1]);
723 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100724 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
725 unsigned int ssllifetime;
726 const char *res;
727
William Lallemand1a748ae2015-05-19 16:37:23 +0200728 if (alertif_too_many_args(1, file, linenum, args, &err_code))
729 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100730 if (*(args[1]) == 0) {
731 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
732 err_code |= ERR_ALERT | ERR_FATAL;
733 goto out;
734 }
735
736 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
737 if (res) {
738 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
739 file, linenum, *res, args[0]);
740 err_code |= ERR_ALERT | ERR_FATAL;
741 goto out;
742 }
743
744 global.tune.ssllifetime = ssllifetime;
745 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100746 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200747 if (alertif_too_many_args(1, file, linenum, args, &err_code))
748 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100749 if (*(args[1]) == 0) {
750 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
751 err_code |= ERR_ALERT | ERR_FATAL;
752 goto out;
753 }
754 global.tune.ssl_max_record = atol(args[1]);
755 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200756#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200757 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
759 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200760 if (*(args[1]) == 0) {
761 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
762 err_code |= ERR_ALERT | ERR_FATAL;
763 goto out;
764 }
765 global.tune.ssl_default_dh_param = atol(args[1]);
766 if (global.tune.ssl_default_dh_param < 1024) {
767 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
768 err_code |= ERR_ALERT | ERR_FATAL;
769 goto out;
770 }
771 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200772#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200773 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
774 if (alertif_too_many_args(1, file, linenum, args, &err_code))
775 goto out;
776 if (*(args[1]) == 0) {
777 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
778 err_code |= ERR_ALERT | ERR_FATAL;
779 goto out;
780 }
781 global.tune.ssl_ctx_cache = atoi(args[1]);
782 if (global.tune.ssl_ctx_cache < 0) {
783 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
784 file, linenum, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200789#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100790 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200791 if (alertif_too_many_args(1, file, linenum, args, &err_code))
792 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100793 if (*(args[1]) == 0) {
794 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
795 err_code |= ERR_ALERT | ERR_FATAL;
796 goto out;
797 }
798 global.tune.buf_limit = atol(args[1]);
799 if (global.tune.buf_limit) {
800 if (global.tune.buf_limit < 3)
801 global.tune.buf_limit = 3;
802 if (global.tune.buf_limit <= global.tune.reserved_bufs)
803 global.tune.buf_limit = global.tune.reserved_bufs + 1;
804 }
805 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100806 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200807 if (alertif_too_many_args(1, file, linenum, args, &err_code))
808 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100809 if (*(args[1]) == 0) {
810 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
811 err_code |= ERR_ALERT | ERR_FATAL;
812 goto out;
813 }
814 global.tune.reserved_bufs = atol(args[1]);
815 if (global.tune.reserved_bufs < 2)
816 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100817 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
818 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100819 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200820 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200823 if (*(args[1]) == 0) {
824 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
825 err_code |= ERR_ALERT | ERR_FATAL;
826 goto out;
827 }
828 global.tune.bufsize = atol(args[1]);
829 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
830 global.tune.maxrewrite = global.tune.bufsize / 2;
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100831 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100832 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200833 }
834 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200835 if (alertif_too_many_args(1, file, linenum, args, &err_code))
836 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200837 if (*(args[1]) == 0) {
838 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
839 err_code |= ERR_ALERT | ERR_FATAL;
840 goto out;
841 }
842 global.tune.maxrewrite = atol(args[1]);
843 if (global.tune.maxrewrite >= global.tune.bufsize / 2)
844 global.tune.maxrewrite = global.tune.bufsize / 2;
845 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100846 else if (!strcmp(args[0], "tune.idletimer")) {
847 unsigned int idle;
848 const char *res;
849
William Lallemand1a748ae2015-05-19 16:37:23 +0200850 if (alertif_too_many_args(1, file, linenum, args, &err_code))
851 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100852 if (*(args[1]) == 0) {
853 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
854 err_code |= ERR_ALERT | ERR_FATAL;
855 goto out;
856 }
857
858 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
859 if (res) {
860 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
861 file, linenum, *res, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
865
866 if (idle > 65535) {
867 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
868 err_code |= ERR_ALERT | ERR_FATAL;
869 goto out;
870 }
871 global.tune.idle_timer = idle;
872 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100873 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200874 if (alertif_too_many_args(1, file, linenum, args, &err_code))
875 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100876 if (global.tune.client_rcvbuf != 0) {
877 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
878 err_code |= ERR_ALERT;
879 goto out;
880 }
881 if (*(args[1]) == 0) {
882 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
883 err_code |= ERR_ALERT | ERR_FATAL;
884 goto out;
885 }
886 global.tune.client_rcvbuf = atol(args[1]);
887 }
888 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200889 if (alertif_too_many_args(1, file, linenum, args, &err_code))
890 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100891 if (global.tune.server_rcvbuf != 0) {
892 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT;
894 goto out;
895 }
896 if (*(args[1]) == 0) {
897 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT | ERR_FATAL;
899 goto out;
900 }
901 global.tune.server_rcvbuf = atol(args[1]);
902 }
903 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200904 if (alertif_too_many_args(1, file, linenum, args, &err_code))
905 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100906 if (global.tune.client_sndbuf != 0) {
907 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
908 err_code |= ERR_ALERT;
909 goto out;
910 }
911 if (*(args[1]) == 0) {
912 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
916 global.tune.client_sndbuf = atol(args[1]);
917 }
918 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200919 if (alertif_too_many_args(1, file, linenum, args, &err_code))
920 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100921 if (global.tune.server_sndbuf != 0) {
922 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
923 err_code |= ERR_ALERT;
924 goto out;
925 }
926 if (*(args[1]) == 0) {
927 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT | ERR_FATAL;
929 goto out;
930 }
931 global.tune.server_sndbuf = atol(args[1]);
932 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200933 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200934 if (alertif_too_many_args(1, file, linenum, args, &err_code))
935 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200936 if (*(args[1]) == 0) {
937 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
938 err_code |= ERR_ALERT | ERR_FATAL;
939 goto out;
940 }
941 global.tune.pipesize = atol(args[1]);
942 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100943 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200944 if (alertif_too_many_args(1, file, linenum, args, &err_code))
945 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100946 if (*(args[1]) == 0) {
947 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
948 err_code |= ERR_ALERT | ERR_FATAL;
949 goto out;
950 }
951 global.tune.cookie_len = atol(args[1]) + 1;
952 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200953 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200954 if (alertif_too_many_args(1, file, linenum, args, &err_code))
955 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200956 if (*(args[1]) == 0) {
957 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
958 err_code |= ERR_ALERT | ERR_FATAL;
959 goto out;
960 }
961 global.tune.max_http_hdr = atol(args[1]);
962 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100963 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
964#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200965 if (alertif_too_many_args(1, file, linenum, args, &err_code))
966 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100967 if (*args[1]) {
968 global.tune.zlibmemlevel = atoi(args[1]);
969 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
970 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
971 file, linenum, args[0]);
972 err_code |= ERR_ALERT | ERR_FATAL;
973 goto out;
974 }
975 } else {
976 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
977 file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981#else
982 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
983 err_code |= ERR_ALERT | ERR_FATAL;
984 goto out;
985#endif
986 }
987 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
988#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200989 if (alertif_too_many_args(1, file, linenum, args, &err_code))
990 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100991 if (*args[1]) {
992 global.tune.zlibwindowsize = atoi(args[1]);
993 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
994 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
995 file, linenum, args[0]);
996 err_code |= ERR_ALERT | ERR_FATAL;
997 goto out;
998 }
999 } else {
1000 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1001 file, linenum, args[0]);
1002 err_code |= ERR_ALERT | ERR_FATAL;
1003 goto out;
1004 }
1005#else
1006 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1007 err_code |= ERR_ALERT | ERR_FATAL;
1008 goto out;
1009#endif
1010 }
William Lallemandf3747832012-11-09 12:33:10 +01001011 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001012 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1013 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001014 if (*args[1]) {
1015 global.tune.comp_maxlevel = atoi(args[1]);
1016 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1017 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1018 file, linenum, args[0]);
1019 err_code |= ERR_ALERT | ERR_FATAL;
1020 goto out;
1021 }
1022 } else {
1023 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1024 file, linenum, args[0]);
1025 err_code |= ERR_ALERT | ERR_FATAL;
1026 goto out;
1027 }
1028 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001029 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1030 if (*args[1]) {
1031 global.tune.pattern_cache = atoi(args[1]);
1032 if (global.tune.pattern_cache < 0) {
1033 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1034 file, linenum, args[0]);
1035 err_code |= ERR_ALERT | ERR_FATAL;
1036 goto out;
1037 }
1038 } else {
1039 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1040 file, linenum, args[0]);
1041 err_code |= ERR_ALERT | ERR_FATAL;
1042 goto out;
1043 }
1044 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001045 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001046 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1047 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001048 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001049 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001050 err_code |= ERR_ALERT;
1051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001052 }
1053 if (*(args[1]) == 0) {
1054 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001057 }
1058 global.uid = atol(args[1]);
1059 }
1060 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001061 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1062 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001063 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001064 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001065 err_code |= ERR_ALERT;
1066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001067 }
1068 if (*(args[1]) == 0) {
1069 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 global.gid = atol(args[1]);
1074 }
Simon Horman98637e52014-06-20 12:30:16 +09001075 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001076 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1077 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001078 global.external_check = 1;
1079 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001080 /* user/group name handling */
1081 else if (!strcmp(args[0], "user")) {
1082 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001083 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1084 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001085 if (global.uid != 0) {
1086 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001087 err_code |= ERR_ALERT;
1088 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001089 }
1090 errno = 0;
1091 ha_user = getpwnam(args[1]);
1092 if (ha_user != NULL) {
1093 global.uid = (int)ha_user->pw_uid;
1094 }
1095 else {
1096 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 +02001097 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001098 }
1099 }
1100 else if (!strcmp(args[0], "group")) {
1101 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001102 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1103 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001104 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001105 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001106 err_code |= ERR_ALERT;
1107 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001108 }
1109 errno = 0;
1110 ha_group = getgrnam(args[1]);
1111 if (ha_group != NULL) {
1112 global.gid = (int)ha_group->gr_gid;
1113 }
1114 else {
1115 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 +02001116 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001117 }
1118 }
1119 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001120 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001121 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 if (*(args[1]) == 0) {
1124 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001125 err_code |= ERR_ALERT | ERR_FATAL;
1126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001127 }
1128 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001129 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1130 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1131 file, linenum, args[0], LONGBITS, global.nbproc);
1132 err_code |= ERR_ALERT | ERR_FATAL;
1133 goto out;
1134 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001135 }
1136 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001137 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1138 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001139 if (global.maxconn != 0) {
1140 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001141 err_code |= ERR_ALERT;
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 }
1144 if (*(args[1]) == 0) {
1145 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001146 err_code |= ERR_ALERT | ERR_FATAL;
1147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001148 }
1149 global.maxconn = atol(args[1]);
1150#ifdef SYSTEM_MAXCONN
1151 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1152 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);
1153 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 }
1156#endif /* SYSTEM_MAXCONN */
1157 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001158 else if (!strcmp(args[0], "maxsslconn")) {
1159#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001160 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1161 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001162 if (*(args[1]) == 0) {
1163 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1164 err_code |= ERR_ALERT | ERR_FATAL;
1165 goto out;
1166 }
1167 global.maxsslconn = atol(args[1]);
1168#else
Emeric Brun0914df82012-10-02 18:45:42 +02001169 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1170 err_code |= ERR_ALERT | ERR_FATAL;
1171 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001172#endif
1173 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001174 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1175#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001176 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1177 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001178 if (*(args[1]) == 0) {
1179 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1180 err_code |= ERR_ALERT | ERR_FATAL;
1181 goto out;
1182 }
1183 free(global.listen_default_ciphers);
1184 global.listen_default_ciphers = strdup(args[1]);
1185#else
1186 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1187 err_code |= ERR_ALERT | ERR_FATAL;
1188 goto out;
1189#endif
1190 }
1191 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1192#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001193 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1194 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001195 if (*(args[1]) == 0) {
1196 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1197 err_code |= ERR_ALERT | ERR_FATAL;
1198 goto out;
1199 }
1200 free(global.connect_default_ciphers);
1201 global.connect_default_ciphers = strdup(args[1]);
1202#else
1203 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1204 err_code |= ERR_ALERT | ERR_FATAL;
1205 goto out;
1206#endif
1207 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001208#ifdef USE_OPENSSL
1209#ifndef OPENSSL_NO_DH
1210 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1211 if (*(args[1]) == 0) {
1212 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1213 err_code |= ERR_ALERT | ERR_FATAL;
1214 goto out;
1215 }
1216 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1217 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1218 err_code |= ERR_ALERT | ERR_FATAL;
1219 goto out;
1220 }
1221 }
1222#endif
1223#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001224 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001225 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1226 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001227 if (*(args[1]) == 0) {
1228 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1229 err_code |= ERR_ALERT | ERR_FATAL;
1230 goto out;
1231 }
1232 if (strcmp(args[1],"none") == 0)
1233 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1234 else if (strcmp(args[1],"required") == 0)
1235 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1236 else {
1237 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
1240 }
1241 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001242 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001243 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1244 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001245 if (global.cps_lim != 0) {
1246 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1247 err_code |= ERR_ALERT;
1248 goto out;
1249 }
1250 if (*(args[1]) == 0) {
1251 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1252 err_code |= ERR_ALERT | ERR_FATAL;
1253 goto out;
1254 }
1255 global.cps_lim = atol(args[1]);
1256 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001257 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001258 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1259 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001260 if (global.sps_lim != 0) {
1261 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1262 err_code |= ERR_ALERT;
1263 goto out;
1264 }
1265 if (*(args[1]) == 0) {
1266 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270 global.sps_lim = atol(args[1]);
1271 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001272 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001273 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1274 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001275 if (global.ssl_lim != 0) {
1276 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1277 err_code |= ERR_ALERT;
1278 goto out;
1279 }
1280 if (*(args[1]) == 0) {
1281 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1282 err_code |= ERR_ALERT | ERR_FATAL;
1283 goto out;
1284 }
1285 global.ssl_lim = atol(args[1]);
1286 }
William Lallemandd85f9172012-11-09 17:05:39 +01001287 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001288 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1289 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001290 if (*(args[1]) == 0) {
1291 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1292 err_code |= ERR_ALERT | ERR_FATAL;
1293 goto out;
1294 }
1295 global.comp_rate_lim = atoi(args[1]) * 1024;
1296 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001297 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001298 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1299 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001300 if (global.maxpipes != 0) {
1301 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001302 err_code |= ERR_ALERT;
1303 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001304 }
1305 if (*(args[1]) == 0) {
1306 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001307 err_code |= ERR_ALERT | ERR_FATAL;
1308 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001309 }
1310 global.maxpipes = atol(args[1]);
1311 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001312 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001313 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1314 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001315 if (*(args[1]) == 0) {
1316 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1317 err_code |= ERR_ALERT | ERR_FATAL;
1318 goto out;
1319 }
William Lallemande3a7d992012-11-20 11:25:20 +01001320 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001321 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001322 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001323 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1324 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
1329 }
1330 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001331 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001332 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1333 err_code |= ERR_ALERT | ERR_FATAL;
1334 goto out;
1335 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001336 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001337
Willy Tarreaubaaee002006-06-26 02:48:02 +02001338 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001339 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1340 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001341 if (global.rlimit_nofile != 0) {
1342 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001343 err_code |= ERR_ALERT;
1344 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001345 }
1346 if (*(args[1]) == 0) {
1347 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001348 err_code |= ERR_ALERT | ERR_FATAL;
1349 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001350 }
1351 global.rlimit_nofile = atol(args[1]);
1352 }
1353 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001354 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001356 if (global.chroot != NULL) {
1357 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001358 err_code |= ERR_ALERT;
1359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001360 }
1361 if (*(args[1]) == 0) {
1362 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT | ERR_FATAL;
1364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
1366 global.chroot = strdup(args[1]);
1367 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001368 else if (!strcmp(args[0], "description")) {
1369 int i, len=0;
1370 char *d;
1371
1372 if (!*args[1]) {
1373 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1374 file, linenum, args[0]);
1375 err_code |= ERR_ALERT | ERR_FATAL;
1376 goto out;
1377 }
1378
Willy Tarreau348acfe2014-04-14 15:00:39 +02001379 for (i = 1; *args[i]; i++)
1380 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001381
1382 if (global.desc)
1383 free(global.desc);
1384
1385 global.desc = d = (char *)calloc(1, len);
1386
Willy Tarreau348acfe2014-04-14 15:00:39 +02001387 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1388 for (i = 2; *args[i]; i++)
1389 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001390 }
1391 else if (!strcmp(args[0], "node")) {
1392 int i;
1393 char c;
1394
William Lallemand1a748ae2015-05-19 16:37:23 +02001395 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1396 goto out;
1397
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001398 for (i=0; args[1][i]; i++) {
1399 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001400 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1401 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001402 break;
1403 }
1404
1405 if (!i || args[1][i]) {
1406 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1407 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1408 file, linenum, args[0]);
1409 err_code |= ERR_ALERT | ERR_FATAL;
1410 goto out;
1411 }
1412
1413 if (global.node)
1414 free(global.node);
1415
1416 global.node = strdup(args[1]);
1417 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001418 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001419 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001421 if (global.pidfile != NULL) {
1422 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001423 err_code |= ERR_ALERT;
1424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 }
1426 if (*(args[1]) == 0) {
1427 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001428 err_code |= ERR_ALERT | ERR_FATAL;
1429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001430 }
1431 global.pidfile = strdup(args[1]);
1432 }
Emeric Bruned760922010-10-22 17:59:25 +02001433 else if (!strcmp(args[0], "unix-bind")) {
1434 int cur_arg = 1;
1435 while (*(args[cur_arg])) {
1436 if (!strcmp(args[cur_arg], "prefix")) {
1437 if (global.unix_bind.prefix != NULL) {
1438 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1439 err_code |= ERR_ALERT;
1440 cur_arg += 2;
1441 continue;
1442 }
1443
1444 if (*(args[cur_arg+1]) == 0) {
1445 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1446 err_code |= ERR_ALERT | ERR_FATAL;
1447 goto out;
1448 }
1449 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1450 cur_arg += 2;
1451 continue;
1452 }
1453
1454 if (!strcmp(args[cur_arg], "mode")) {
1455
1456 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1457 cur_arg += 2;
1458 continue;
1459 }
1460
1461 if (!strcmp(args[cur_arg], "uid")) {
1462
1463 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1464 cur_arg += 2;
1465 continue;
1466 }
1467
1468 if (!strcmp(args[cur_arg], "gid")) {
1469
1470 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1471 cur_arg += 2;
1472 continue;
1473 }
1474
1475 if (!strcmp(args[cur_arg], "user")) {
1476 struct passwd *user;
1477
1478 user = getpwnam(args[cur_arg + 1]);
1479 if (!user) {
1480 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1481 file, linenum, args[0], args[cur_arg + 1 ]);
1482 err_code |= ERR_ALERT | ERR_FATAL;
1483 goto out;
1484 }
1485
1486 global.unix_bind.ux.uid = user->pw_uid;
1487 cur_arg += 2;
1488 continue;
1489 }
1490
1491 if (!strcmp(args[cur_arg], "group")) {
1492 struct group *group;
1493
1494 group = getgrnam(args[cur_arg + 1]);
1495 if (!group) {
1496 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1497 file, linenum, args[0], args[cur_arg + 1 ]);
1498 err_code |= ERR_ALERT | ERR_FATAL;
1499 goto out;
1500 }
1501
1502 global.unix_bind.ux.gid = group->gr_gid;
1503 cur_arg += 2;
1504 continue;
1505 }
1506
Willy Tarreaub48f9582011-09-05 01:17:06 +02001507 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001508 file, linenum, args[0]);
1509 err_code |= ERR_ALERT | ERR_FATAL;
1510 goto out;
1511 }
1512 }
William Lallemand0f99e342011-10-12 17:50:54 +02001513 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1514 /* delete previous herited or defined syslog servers */
1515 struct logsrv *back;
1516 struct logsrv *tmp;
1517
1518 if (*(args[1]) != 0) {
1519 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1520 err_code |= ERR_ALERT | ERR_FATAL;
1521 goto out;
1522 }
1523
1524 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1525 LIST_DEL(&tmp->list);
1526 free(tmp);
1527 }
1528 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001529 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001530 struct sockaddr_storage *sk;
1531 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001532 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001533 int arg = 0;
1534 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001535
William Lallemand1a748ae2015-05-19 16:37:23 +02001536 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1537 goto out;
1538
Willy Tarreaubaaee002006-06-26 02:48:02 +02001539 if (*(args[1]) == 0 || *(args[2]) == 0) {
1540 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001541 err_code |= ERR_ALERT | ERR_FATAL;
1542 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001543 }
William Lallemand0f99e342011-10-12 17:50:54 +02001544
1545 logsrv = calloc(1, sizeof(struct logsrv));
1546
Willy Tarreau18324f52014-06-27 18:10:07 +02001547 /* just after the address, a length may be specified */
1548 if (strcmp(args[arg+2], "len") == 0) {
1549 len = atoi(args[arg+3]);
1550 if (len < 80 || len > 65535) {
1551 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1552 file, linenum, args[arg+3]);
1553 err_code |= ERR_ALERT | ERR_FATAL;
1554 goto out;
1555 }
1556 logsrv->maxlen = len;
1557
1558 /* skip these two args */
1559 arg += 2;
1560 }
1561 else
1562 logsrv->maxlen = MAX_SYSLOG_LEN;
1563
1564 if (logsrv->maxlen > global.max_syslog_len) {
1565 global.max_syslog_len = logsrv->maxlen;
1566 logline = realloc(logline, global.max_syslog_len + 1);
1567 }
1568
William Lallemand1a748ae2015-05-19 16:37:23 +02001569 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1570 goto out;
1571
Willy Tarreau18324f52014-06-27 18:10:07 +02001572 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001573 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001574 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001575 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001576 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001577 }
1578
William Lallemand0f99e342011-10-12 17:50:54 +02001579 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001580 if (*(args[arg+3])) {
1581 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001582 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001583 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001584 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001585 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001586 }
1587 }
1588
William Lallemand0f99e342011-10-12 17:50:54 +02001589 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001590 if (*(args[arg+4])) {
1591 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001592 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001593 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001594 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001595 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001596 }
1597 }
1598
Willy Tarreau902636f2013-03-10 19:44:48 +01001599 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001600 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001601 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001602 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001603 free(logsrv);
1604 goto out;
1605 }
1606 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001607
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001608 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001609 if (port1 != port2) {
1610 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1611 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001612 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001613 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001614 goto out;
1615 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001616
William Lallemand0f99e342011-10-12 17:50:54 +02001617 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001618 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001619 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001620 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001621
William Lallemand0f99e342011-10-12 17:50:54 +02001622 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001623 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001624 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1625 char *name;
1626 int len;
1627
1628 if (global.log_send_hostname != NULL) {
1629 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1630 err_code |= ERR_ALERT;
1631 goto out;
1632 }
1633
1634 if (*(args[1]))
1635 name = args[1];
1636 else
1637 name = hostname;
1638
1639 len = strlen(name);
1640
1641 /* We'll add a space after the name to respect the log format */
1642 free(global.log_send_hostname);
1643 global.log_send_hostname = malloc(len + 2);
1644 snprintf(global.log_send_hostname, len + 2, "%s ", name);
1645 }
Kevinm48936af2010-12-22 16:08:21 +00001646 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001647 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1648 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001649 if (*(args[1]) == 0) {
1650 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1651 err_code |= ERR_ALERT | ERR_FATAL;
1652 goto out;
1653 }
1654 free(global.log_tag);
1655 global.log_tag = strdup(args[1]);
1656 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001657 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001658 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1659 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001660 if (global.spread_checks != 0) {
1661 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001662 err_code |= ERR_ALERT;
1663 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001664 }
1665 if (*(args[1]) == 0) {
1666 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001667 err_code |= ERR_ALERT | ERR_FATAL;
1668 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001669 }
1670 global.spread_checks = atol(args[1]);
1671 if (global.spread_checks < 0 || global.spread_checks > 50) {
1672 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001675 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001676 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1677 const char *err;
1678 unsigned int val;
1679
William Lallemand1a748ae2015-05-19 16:37:23 +02001680 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1681 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001682 if (*(args[1]) == 0) {
1683 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1684 err_code |= ERR_ALERT | ERR_FATAL;
1685 goto out;
1686 }
1687
1688 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1689 if (err) {
1690 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1691 err_code |= ERR_ALERT | ERR_FATAL;
1692 }
1693 global.max_spread_checks = val;
1694 if (global.max_spread_checks < 0) {
1695 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1696 err_code |= ERR_ALERT | ERR_FATAL;
1697 }
1698 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001699 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1700#ifdef USE_CPU_AFFINITY
1701 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001702 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001703 unsigned long cpus = 0;
1704
1705 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001706 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001707 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001708 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001709 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001710 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001711 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001712 proc = atol(args[1]);
1713 if (proc >= 1 && proc <= LONGBITS)
1714 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001715 }
1716
1717 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001718 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",
1719 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001720 err_code |= ERR_ALERT | ERR_FATAL;
1721 goto out;
1722 }
1723
1724 cur_arg = 2;
1725 while (*args[cur_arg]) {
1726 unsigned int low, high;
1727
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001728 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001729 char *dash = strchr(args[cur_arg], '-');
1730
1731 low = high = str2uic(args[cur_arg]);
1732 if (dash)
1733 high = str2uic(dash + 1);
1734
1735 if (high < low) {
1736 unsigned int swap = low;
1737 low = high;
1738 high = swap;
1739 }
1740
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001741 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001742 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001743 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001744 err_code |= ERR_ALERT | ERR_FATAL;
1745 goto out;
1746 }
1747
1748 while (low <= high)
1749 cpus |= 1UL << low++;
1750 }
1751 else {
1752 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1753 file, linenum, args[0], args[cur_arg]);
1754 err_code |= ERR_ALERT | ERR_FATAL;
1755 goto out;
1756 }
1757 cur_arg++;
1758 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001759 for (i = 0; i < LONGBITS; i++)
1760 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001761 global.cpu_map[i] = cpus;
1762#else
1763 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 goto out;
1766#endif
1767 }
Thomas Holmes0809f262015-05-12 15:50:47 +01001768#ifdef USE_51DEGREES
1769 else if (strcmp(args[0], "51degrees-data-file") == 0) {
1770 if(!*(args[1])) {
Thomas Holmes4d441a72015-05-29 12:54:25 +01001771 Alert("parsing [%s:%d]: '%s' expects a filepath to a 51Degrees trie or pattern data file.\n", file, linenum, args[0]);
Thomas Holmes0809f262015-05-12 15:50:47 +01001772 err_code |= ERR_ALERT | ERR_FATAL;
1773 goto out;
1774 }
1775 global._51d_data_file_path = strdup(args[1]);
1776 }
1777 else if (strcmp(args[0], "51degrees-property-seperator") == 0) {
1778 if(!*(args[1])) {
Thomas Holmes4d441a72015-05-29 12:54:25 +01001779 Alert("parsing [%s:%d]: '%s' expects a single character.\n", file, linenum, args[0]);
Thomas Holmes0809f262015-05-12 15:50:47 +01001780 err_code |= ERR_ALERT | ERR_FATAL;
1781 goto out;
1782 }
1783 if (strlen(args[1]) > 1) {
Thomas Holmes4d441a72015-05-29 12:54:25 +01001784 Alert("parsing [%s:%d]: '%s' expects a single character, got '%s'.\n", file, linenum, args[0], args[1]);
Thomas Holmes0809f262015-05-12 15:50:47 +01001785 err_code |= ERR_ALERT | ERR_FATAL;
1786 goto out;
1787 }
1788 global._51d_property_seperator = *args[1];
1789 }
1790 else if (strcmp(args[0], "51degrees-property-name-list") == 0) {
1791 int arg;
1792 struct _51d_property_names *name;
1793
1794 arg = 1;
1795 if (!*args[arg]) {
1796 Alert("parsing [%s:%d]: '%s' expects at least one 51Degrees property name.\n", file, linenum, args[0]);
1797 err_code |= ERR_ALERT | ERR_FATAL;
1798 goto out;
1799 }
1800
1801 LIST_INIT(&global._51d_property_names);
1802 while (*args[arg]) {
1803 name = calloc(1, sizeof(struct _51d_property_names));
1804 name->name = strdup(args[arg]);
1805 LIST_ADDQ(&global._51d_property_names, &name->list);
1806 ++arg;
1807 }
1808 }
1809#endif
Willy Tarreaubaaee002006-06-26 02:48:02 +02001810 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001811 struct cfg_kw_list *kwl;
1812 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001813 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001814
1815 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1816 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1817 if (kwl->kw[index].section != CFG_GLOBAL)
1818 continue;
1819 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001820 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001821 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001822 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001823 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001824 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001825 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001826 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001827 err_code |= ERR_WARN;
1828 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001829 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001830 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001831 }
1832 }
1833 }
1834
Willy Tarreaubaaee002006-06-26 02:48:02 +02001835 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001836 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001837 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001838
Willy Tarreau058e9072009-07-20 09:30:05 +02001839 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001840 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001841 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001842}
1843
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001844void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001845{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001846 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001847 defproxy.mode = PR_MODE_TCP;
1848 defproxy.state = PR_STNEW;
1849 defproxy.maxconn = cfg_maxpconn;
1850 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001851 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001852
Simon Horman66183002013-02-23 10:16:43 +09001853 defproxy.defsrv.check.inter = DEF_CHKINTR;
1854 defproxy.defsrv.check.fastinter = 0;
1855 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001856 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1857 defproxy.defsrv.agent.fastinter = 0;
1858 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001859 defproxy.defsrv.check.rise = DEF_RISETIME;
1860 defproxy.defsrv.check.fall = DEF_FALLTIME;
1861 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1862 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001863 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001864 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001865 defproxy.defsrv.maxqueue = 0;
1866 defproxy.defsrv.minconn = 0;
1867 defproxy.defsrv.maxconn = 0;
1868 defproxy.defsrv.slowstart = 0;
1869 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1870 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1871 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001872
1873 defproxy.email_alert.level = LOG_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001874}
1875
Willy Tarreauade5ec42010-01-28 19:33:49 +01001876
Willy Tarreau63af98d2014-05-18 08:11:41 +02001877/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1878 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1879 * ERR_FATAL in case of error.
1880 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001881static int create_cond_regex_rule(const char *file, int line,
1882 struct proxy *px, int dir, int action, int flags,
1883 const char *cmd, const char *reg, const char *repl,
1884 const char **cond_start)
1885{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001886 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001887 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001888 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001889 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001890 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001891 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001892 int cs;
1893 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001894
1895 if (px == &defproxy) {
1896 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001897 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001898 goto err;
1899 }
1900
1901 if (*reg == 0) {
1902 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001903 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001904 goto err;
1905 }
1906
1907 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001908 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001909
Willy Tarreau5321c422010-01-28 20:35:13 +01001910 if (cond_start &&
1911 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001912 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
1913 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
1914 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001915 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001916 goto err;
1917 }
1918 }
1919 else if (cond_start && **cond_start) {
1920 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
1921 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001922 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01001923 goto err;
1924 }
1925
Willy Tarreau63af98d2014-05-18 08:11:41 +02001926 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01001927 (dir == SMP_OPT_DIR_REQ) ?
1928 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
1929 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
1930 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01001931
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001932 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01001933 if (!preg) {
1934 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001935 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001936 goto err;
1937 }
1938
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001939 cs = !(flags & REG_ICASE);
1940 cap = !(flags & REG_NOSUB);
1941 error = NULL;
1942 if (!regex_comp(reg, preg, cs, cap, &error)) {
1943 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
1944 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001945 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001946 goto err;
1947 }
1948
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001949 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01001950 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001951 if (repl && err) {
1952 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
1953 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001954 ret_code |= ERR_ALERT | ERR_FATAL;
1955 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001956 }
1957
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02001958 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02001959 ret_code |= ERR_WARN;
1960
1961 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001962
Willy Tarreau63af98d2014-05-18 08:11:41 +02001963 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001964 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01001965 err:
1966 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001967 free(errmsg);
1968 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001969}
1970
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971/*
William Lallemand51097192015-04-14 16:35:22 +02001972 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02001973 * Returns the error code, 0 if OK, or any combination of :
1974 * - ERR_ABORT: must abort ASAP
1975 * - ERR_FATAL: we can continue parsing but not start the service
1976 * - ERR_WARN: a warning has been emitted
1977 * - ERR_ALERT: an alert has been emitted
1978 * Only the two first ones can stop processing, the two others are just
1979 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02001980 */
Emeric Brun32da3c42010-09-23 18:39:19 +02001981int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
1982{
1983 static struct peers *curpeers = NULL;
1984 struct peer *newpeer = NULL;
1985 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02001986 struct bind_conf *bind_conf;
1987 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02001988 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01001989 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02001990
1991 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001992 if (!*args[1]) {
1993 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01001994 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01001995 goto out;
1996 }
Emeric Brun32da3c42010-09-23 18:39:19 +02001997
William Lallemand6e62fb62015-04-28 16:55:23 +02001998 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1999 goto out;
2000
Emeric Brun32da3c42010-09-23 18:39:19 +02002001 err = invalid_char(args[1]);
2002 if (err) {
2003 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2004 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002005 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002006 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002007 }
2008
2009 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2010 /*
2011 * If there are two proxies with the same name only following
2012 * combinations are allowed:
2013 */
2014 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002015 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 +02002016 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002017 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002018 }
2019 }
2020
2021 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2022 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2023 err_code |= ERR_ALERT | ERR_ABORT;
2024 goto out;
2025 }
2026
2027 curpeers->next = peers;
2028 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002029 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002030 curpeers->conf.line = linenum;
2031 curpeers->last_change = now.tv_sec;
2032 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002033 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002034 }
2035 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002036 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002037 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002038 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002039
2040 if (!*args[2]) {
2041 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2042 file, linenum, args[0]);
2043 err_code |= ERR_ALERT | ERR_FATAL;
2044 goto out;
2045 }
2046
2047 err = invalid_char(args[1]);
2048 if (err) {
2049 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2050 file, linenum, *err, args[1]);
2051 err_code |= ERR_ALERT | ERR_FATAL;
2052 goto out;
2053 }
2054
2055 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2056 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2057 err_code |= ERR_ALERT | ERR_ABORT;
2058 goto out;
2059 }
2060
2061 /* the peers are linked backwards first */
2062 curpeers->count++;
2063 newpeer->next = curpeers->remote;
2064 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002065 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002066 newpeer->conf.line = linenum;
2067
2068 newpeer->last_change = now.tv_sec;
2069 newpeer->id = strdup(args[1]);
2070
Willy Tarreau902636f2013-03-10 19:44:48 +01002071 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002072 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002073 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002074 err_code |= ERR_ALERT | ERR_FATAL;
2075 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002076 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002077
2078 proto = protocol_by_family(sk->ss_family);
2079 if (!proto || !proto->connect) {
2080 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2081 file, linenum, args[0], args[1]);
2082 err_code |= ERR_ALERT | ERR_FATAL;
2083 goto out;
2084 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002085
2086 if (port1 != port2) {
2087 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2088 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002089 err_code |= ERR_ALERT | ERR_FATAL;
2090 goto out;
2091 }
2092
Willy Tarreau2aa38802013-02-20 19:20:59 +01002093 if (!port1) {
2094 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2095 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002096 err_code |= ERR_ALERT | ERR_FATAL;
2097 goto out;
2098 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002099
Emeric Brun32da3c42010-09-23 18:39:19 +02002100 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002101 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002102 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002103 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002104
Emeric Brun32da3c42010-09-23 18:39:19 +02002105 if (strcmp(newpeer->id, localpeer) == 0) {
2106 /* Current is local peer, it define a frontend */
2107 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002108 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002109
2110 if (!curpeers->peers_fe) {
2111 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2112 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2113 err_code |= ERR_ALERT | ERR_ABORT;
2114 goto out;
2115 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002116
Willy Tarreau237250c2011-07-29 01:49:03 +02002117 init_new_proxy(curpeers->peers_fe);
2118 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002119 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002120 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2121 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002122 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002123
2124 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2125
Willy Tarreau902636f2013-03-10 19:44:48 +01002126 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2127 if (errmsg && *errmsg) {
2128 indent_msg(&errmsg, 2);
2129 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002130 }
2131 else
2132 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2133 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002134 err_code |= ERR_FATAL;
2135 goto out;
2136 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002137
2138 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002139 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002140 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2141 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002142 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002143 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002144 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002145 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002146 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2147 global.maxsock += l->maxconn;
2148 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002149 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002150 else {
2151 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2152 file, linenum, args[0], args[1],
2153 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2154 err_code |= ERR_FATAL;
2155 goto out;
2156 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002157 }
2158 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002159 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2160 curpeers->state = PR_STSTOPPED;
2161 }
2162 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2163 curpeers->state = PR_STNEW;
2164 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002165 else if (*args[0] != 0) {
2166 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2167 err_code |= ERR_ALERT | ERR_FATAL;
2168 goto out;
2169 }
2170
2171out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002172 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002173 return err_code;
2174}
2175
Simon Horman0d16a402015-01-30 11:22:58 +09002176
2177/*
William Lallemand51097192015-04-14 16:35:22 +02002178 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002179 * Returns the error code, 0 if OK, or any combination of :
2180 * - ERR_ABORT: must abort ASAP
2181 * - ERR_FATAL: we can continue parsing but not start the service
2182 * - ERR_WARN: a warning has been emitted
2183 * - ERR_ALERT: an alert has been emitted
2184 * Only the two first ones can stop processing, the two others are just
2185 * indicators.
2186 */
2187int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2188{
2189 static struct mailers *curmailers = NULL;
2190 struct mailer *newmailer = NULL;
2191 const char *err;
2192 int err_code = 0;
2193 char *errmsg = NULL;
2194
2195 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2196 if (!*args[1]) {
2197 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2198 err_code |= ERR_ALERT | ERR_ABORT;
2199 goto out;
2200 }
2201
2202 err = invalid_char(args[1]);
2203 if (err) {
2204 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2205 file, linenum, *err, args[0], args[1]);
2206 err_code |= ERR_ALERT | ERR_ABORT;
2207 goto out;
2208 }
2209
2210 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2211 /*
2212 * If there are two proxies with the same name only following
2213 * combinations are allowed:
2214 */
2215 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002216 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 +09002217 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002218 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002219 }
2220 }
2221
2222 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2223 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2224 err_code |= ERR_ALERT | ERR_ABORT;
2225 goto out;
2226 }
2227
2228 curmailers->next = mailers;
2229 mailers = curmailers;
2230 curmailers->conf.file = strdup(file);
2231 curmailers->conf.line = linenum;
2232 curmailers->id = strdup(args[1]);
2233 }
2234 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2235 struct sockaddr_storage *sk;
2236 int port1, port2;
2237 struct protocol *proto;
2238
2239 if (!*args[2]) {
2240 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2241 file, linenum, args[0]);
2242 err_code |= ERR_ALERT | ERR_FATAL;
2243 goto out;
2244 }
2245
2246 err = invalid_char(args[1]);
2247 if (err) {
2248 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2249 file, linenum, *err, args[1]);
2250 err_code |= ERR_ALERT | ERR_FATAL;
2251 goto out;
2252 }
2253
2254 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2255 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2256 err_code |= ERR_ALERT | ERR_ABORT;
2257 goto out;
2258 }
2259
2260 /* the mailers are linked backwards first */
2261 curmailers->count++;
2262 newmailer->next = curmailers->mailer_list;
2263 curmailers->mailer_list = newmailer;
2264 newmailer->mailers = curmailers;
2265 newmailer->conf.file = strdup(file);
2266 newmailer->conf.line = linenum;
2267
2268 newmailer->id = strdup(args[1]);
2269
2270 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL);
2271 if (!sk) {
2272 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2273 err_code |= ERR_ALERT | ERR_FATAL;
2274 goto out;
2275 }
2276
2277 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002278 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2279 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002280 file, linenum, args[0], args[1]);
2281 err_code |= ERR_ALERT | ERR_FATAL;
2282 goto out;
2283 }
2284
2285 if (port1 != port2) {
2286 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2287 file, linenum, args[0], args[1], args[2]);
2288 err_code |= ERR_ALERT | ERR_FATAL;
2289 goto out;
2290 }
2291
2292 if (!port1) {
2293 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2294 file, linenum, args[0], args[1], args[2]);
2295 err_code |= ERR_ALERT | ERR_FATAL;
2296 goto out;
2297 }
2298
2299 newmailer->addr = *sk;
2300 newmailer->proto = proto;
2301 newmailer->xprt = &raw_sock;
2302 newmailer->sock_init_arg = NULL;
2303 } /* neither "mailer" nor "mailers" */
2304 else if (*args[0] != 0) {
2305 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2306 err_code |= ERR_ALERT | ERR_FATAL;
2307 goto out;
2308 }
2309
2310out:
2311 free(errmsg);
2312 return err_code;
2313}
2314
Simon Horman9dc49962015-01-30 11:22:59 +09002315static void free_email_alert(struct proxy *p)
2316{
2317 free(p->email_alert.mailers.name);
2318 p->email_alert.mailers.name = NULL;
2319 free(p->email_alert.from);
2320 p->email_alert.from = NULL;
2321 free(p->email_alert.to);
2322 p->email_alert.to = NULL;
2323 free(p->email_alert.myhostname);
2324 p->email_alert.myhostname = NULL;
2325}
2326
Willy Tarreau3842f002009-06-14 11:39:52 +02002327int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002328{
2329 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002330 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002331 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002332 int rc;
2333 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002334 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002335 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002336 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002337 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002338 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002339
Willy Tarreau977b8e42006-12-29 14:19:17 +01002340 if (!strcmp(args[0], "listen"))
2341 rc = PR_CAP_LISTEN;
2342 else if (!strcmp(args[0], "frontend"))
2343 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002344 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002345 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002346 else
2347 rc = PR_CAP_NONE;
2348
2349 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002350 if (!*args[1]) {
2351 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2352 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2353 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002354 err_code |= ERR_ALERT | ERR_ABORT;
2355 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002356 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002357
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002358 err = invalid_char(args[1]);
2359 if (err) {
2360 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2361 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002362 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002363 }
2364
Willy Tarreau8f50b682015-05-26 11:45:02 +02002365 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2366 if (curproxy) {
2367 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2368 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2369 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002370 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002371 }
2372
Willy Tarreaubaaee002006-06-26 02:48:02 +02002373 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2374 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002375 err_code |= ERR_ALERT | ERR_ABORT;
2376 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002377 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002378
Willy Tarreau97cb7802010-01-03 20:23:58 +01002379 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002380 curproxy->next = proxy;
2381 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002382 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2383 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002384 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002385 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002386 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002387 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002388
William Lallemand6e62fb62015-04-28 16:55:23 +02002389 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2390 if (curproxy->cap & PR_CAP_FE)
2391 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002393 }
2394
2395 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002396 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002397 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002398
Willy Tarreaubaaee002006-06-26 02:48:02 +02002399 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002400 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002401 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002402 curproxy->no_options = defproxy.no_options;
2403 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002404 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002405 curproxy->except_net = defproxy.except_net;
2406 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002407 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002408 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002409
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002410 if (defproxy.fwdfor_hdr_len) {
2411 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2412 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2413 }
2414
Willy Tarreaub86db342009-11-30 11:50:16 +01002415 if (defproxy.orgto_hdr_len) {
2416 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2417 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2418 }
2419
Mark Lamourinec2247f02012-01-04 13:02:01 -05002420 if (defproxy.server_id_hdr_len) {
2421 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2422 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2423 }
2424
Willy Tarreau977b8e42006-12-29 14:19:17 +01002425 if (curproxy->cap & PR_CAP_FE) {
2426 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002427 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002428 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002429
2430 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002431 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2432 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002433
2434 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002436
Willy Tarreau977b8e42006-12-29 14:19:17 +01002437 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002438 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002439 curproxy->fullconn = defproxy.fullconn;
2440 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002441 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002442 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002443
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002444 if (defproxy.check_req) {
2445 curproxy->check_req = calloc(1, defproxy.check_len);
2446 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2447 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002448 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002449
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002450 if (defproxy.expect_str) {
2451 curproxy->expect_str = strdup(defproxy.expect_str);
2452 if (defproxy.expect_regex) {
2453 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002454 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2455 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002456 }
2457 }
2458
Willy Tarreau67402132012-05-31 20:40:20 +02002459 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002460 if (defproxy.cookie_name)
2461 curproxy->cookie_name = strdup(defproxy.cookie_name);
2462 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002463 if (defproxy.cookie_domain)
2464 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002465
Willy Tarreau31936852010-10-06 16:59:56 +02002466 if (defproxy.cookie_maxidle)
2467 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2468
2469 if (defproxy.cookie_maxlife)
2470 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2471
Emeric Brun647caf12009-06-30 17:57:00 +02002472 if (defproxy.rdp_cookie_name)
2473 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2474 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2475
Willy Tarreau01732802007-11-01 22:48:15 +01002476 if (defproxy.url_param_name)
2477 curproxy->url_param_name = strdup(defproxy.url_param_name);
2478 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002479
Benoitaffb4812009-03-25 13:02:10 +01002480 if (defproxy.hh_name)
2481 curproxy->hh_name = strdup(defproxy.hh_name);
2482 curproxy->hh_len = defproxy.hh_len;
2483 curproxy->hh_match_domain = defproxy.hh_match_domain;
2484
Willy Tarreauef9a3602012-12-08 22:29:20 +01002485 if (defproxy.conn_src.iface_name)
2486 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2487 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002488 curproxy->conn_src.opts = defproxy.conn_src.opts;
Pieter Baauwd551fb52013-05-08 22:49:23 +02002489#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002490 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002491#endif
Willy Tarreau977b8e42006-12-29 14:19:17 +01002492 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002493
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002494 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002495 if (defproxy.capture_name)
2496 curproxy->capture_name = strdup(defproxy.capture_name);
2497 curproxy->capture_namelen = defproxy.capture_namelen;
2498 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002499 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002500
Willy Tarreau977b8e42006-12-29 14:19:17 +01002501 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002502 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002503 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002504 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002505 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002506 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002507 curproxy->mon_net = defproxy.mon_net;
2508 curproxy->mon_mask = defproxy.mon_mask;
2509 if (defproxy.monitor_uri)
2510 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2511 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002512 if (defproxy.defbe.name)
2513 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002514
2515 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002516 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2517 if (curproxy->conf.logformat_string &&
2518 curproxy->conf.logformat_string != default_http_log_format &&
2519 curproxy->conf.logformat_string != default_tcp_log_format &&
2520 curproxy->conf.logformat_string != clf_http_log_format)
2521 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2522
2523 if (defproxy.conf.lfs_file) {
2524 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2525 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2526 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002527 }
2528
2529 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002530 curproxy->timeout.connect = defproxy.timeout.connect;
2531 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002532 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002533 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002534 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002535 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002536 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002537 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002538 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002539 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002540 }
2541
Willy Tarreaubaaee002006-06-26 02:48:02 +02002542 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002543 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002544
2545 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002546 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002547 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002548 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002549 LIST_INIT(&node->list);
2550 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2551 }
2552
Willy Tarreau62a61232013-04-12 18:13:46 +02002553 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2554 if (curproxy->conf.uniqueid_format_string)
2555 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2556
Willy Tarreau094af4e2015-01-07 15:03:42 +01002557 if (defproxy.log_tag)
2558 curproxy->log_tag = strdup(defproxy.log_tag);
2559
Willy Tarreau62a61232013-04-12 18:13:46 +02002560 if (defproxy.conf.uif_file) {
2561 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2562 curproxy->conf.uif_line = defproxy.conf.uif_line;
2563 }
William Lallemanda73203e2012-03-12 12:48:57 +01002564
2565 /* copy default header unique id */
2566 if (defproxy.header_unique_id)
2567 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2568
William Lallemand82fe75c2012-10-23 10:25:10 +02002569 /* default compression options */
2570 if (defproxy.comp != NULL) {
2571 curproxy->comp = calloc(1, sizeof(struct comp));
2572 curproxy->comp->algos = defproxy.comp->algos;
2573 curproxy->comp->types = defproxy.comp->types;
2574 }
2575
Willy Tarreaubaaee002006-06-26 02:48:02 +02002576 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002577 curproxy->conf.used_listener_id = EB_ROOT;
2578 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002579
Simon Horman98637e52014-06-20 12:30:16 +09002580 if (defproxy.check_path)
2581 curproxy->check_path = strdup(defproxy.check_path);
2582 if (defproxy.check_command)
2583 curproxy->check_command = strdup(defproxy.check_command);
2584
Simon Horman9dc49962015-01-30 11:22:59 +09002585 if (defproxy.email_alert.mailers.name)
2586 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2587 if (defproxy.email_alert.from)
2588 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2589 if (defproxy.email_alert.to)
2590 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2591 if (defproxy.email_alert.myhostname)
2592 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002593 curproxy->email_alert.level = defproxy.email_alert.level;
Simon Horman9dc49962015-01-30 11:22:59 +09002594
Willy Tarreau93893792009-07-23 13:19:11 +02002595 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002596 }
2597 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2598 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002599 /* FIXME-20070101: we should do this too at the end of the
2600 * config parsing to free all default values.
2601 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002602 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2603 err_code |= ERR_ABORT;
2604 goto out;
2605 }
2606
Willy Tarreaua534fea2008-08-03 12:19:50 +02002607 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002608 free(defproxy.check_command);
2609 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002610 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002611 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002612 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002613 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002614 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002615 free(defproxy.capture_name);
2616 free(defproxy.monitor_uri);
2617 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002618 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002619 free(defproxy.fwdfor_hdr_name);
2620 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002621 free(defproxy.orgto_hdr_name);
2622 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002623 free(defproxy.server_id_hdr_name);
2624 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002625 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002626 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002627 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002628 free(defproxy.expect_regex);
2629 defproxy.expect_regex = NULL;
2630 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002631
Willy Tarreau62a61232013-04-12 18:13:46 +02002632 if (defproxy.conf.logformat_string != default_http_log_format &&
2633 defproxy.conf.logformat_string != default_tcp_log_format &&
2634 defproxy.conf.logformat_string != clf_http_log_format)
2635 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002636
Willy Tarreau62a61232013-04-12 18:13:46 +02002637 free(defproxy.conf.uniqueid_format_string);
2638 free(defproxy.conf.lfs_file);
2639 free(defproxy.conf.uif_file);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002640 free(defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002641 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002642
Willy Tarreaua534fea2008-08-03 12:19:50 +02002643 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002644 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002645
Willy Tarreaubaaee002006-06-26 02:48:02 +02002646 /* we cannot free uri_auth because it might already be used */
2647 init_default_instance();
2648 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002649 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2650 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002651 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002652 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002653 }
2654 else if (curproxy == NULL) {
2655 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002656 err_code |= ERR_ALERT | ERR_FATAL;
2657 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002658 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002659
2660 /* update the current file and line being parsed */
2661 curproxy->conf.args.file = curproxy->conf.file;
2662 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002663
2664 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002665 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2666 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2667 if (err_code & ERR_FATAL)
2668 goto out;
2669 }
2670 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002671 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002672 int cur_arg;
2673
Willy Tarreaubaaee002006-06-26 02:48:02 +02002674 if (curproxy == &defproxy) {
2675 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002676 err_code |= ERR_ALERT | ERR_FATAL;
2677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002680 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681
Willy Tarreau24709282013-03-10 21:32:12 +01002682 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002683 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002684 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002685 err_code |= ERR_ALERT | ERR_FATAL;
2686 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002687 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002688
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002689 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002690
2691 /* use default settings for unix sockets */
2692 bind_conf->ux.uid = global.unix_bind.ux.uid;
2693 bind_conf->ux.gid = global.unix_bind.ux.gid;
2694 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02002695
2696 /* NOTE: the following line might create several listeners if there
2697 * are comma-separated IPs or port ranges. So all further processing
2698 * will have to be applied to all listeners created after last_listen.
2699 */
Willy Tarreau902636f2013-03-10 19:44:48 +01002700 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
2701 if (errmsg && *errmsg) {
2702 indent_msg(&errmsg, 2);
2703 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002704 }
2705 else
2706 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
2707 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002708 err_code |= ERR_ALERT | ERR_FATAL;
2709 goto out;
2710 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002711
Willy Tarreau4348fad2012-09-20 16:48:07 +02002712 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
2713 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01002714 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02002715 }
2716
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002717 cur_arg = 2;
2718 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02002719 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02002720 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02002721 char *err;
2722
Willy Tarreau26982662012-09-12 23:17:10 +02002723 kw = bind_find_kw(args[cur_arg]);
2724 if (kw) {
2725 char *err = NULL;
2726 int code;
2727
2728 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02002729 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
2730 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002731 cur_arg += 1 + kw->skip ;
2732 err_code |= ERR_ALERT | ERR_FATAL;
2733 goto out;
2734 }
2735
Willy Tarreau4348fad2012-09-20 16:48:07 +02002736 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02002737 err_code |= code;
2738
2739 if (code) {
2740 if (err && *err) {
2741 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02002742 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02002743 }
2744 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02002745 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
2746 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02002747 if (code & ERR_FATAL) {
2748 free(err);
2749 cur_arg += 1 + kw->skip;
2750 goto out;
2751 }
2752 }
2753 free(err);
2754 cur_arg += 1 + kw->skip;
2755 continue;
2756 }
2757
Willy Tarreau8638f482012-09-18 18:01:17 +02002758 err = NULL;
2759 if (!bind_dumped) {
2760 bind_dump_kws(&err);
2761 indent_msg(&err, 4);
2762 bind_dumped = 1;
2763 }
2764
2765 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
2766 file, linenum, args[0], args[1], args[cur_arg],
2767 err ? " Registered keywords :" : "", err ? err : "");
2768 free(err);
2769
Willy Tarreau93893792009-07-23 13:19:11 +02002770 err_code |= ERR_ALERT | ERR_FATAL;
2771 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002772 }
Willy Tarreau93893792009-07-23 13:19:11 +02002773 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002774 }
2775 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01002776 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
2778 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002779 err_code |= ERR_ALERT | ERR_FATAL;
2780 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002781 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002782 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002783 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002784
Willy Tarreaubaaee002006-06-26 02:48:02 +02002785 /* flush useless bits */
2786 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02002787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02002789 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01002790 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002791 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002792
William Lallemanddf1425a2015-04-28 20:17:49 +02002793 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2794 goto out;
2795
Willy Tarreau1c47f852006-07-09 08:22:27 +02002796 if (!*args[1]) {
2797 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
2798 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002799 err_code |= ERR_ALERT | ERR_FATAL;
2800 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002801 }
2802
Willy Tarreaua534fea2008-08-03 12:19:50 +02002803 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002804 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002805 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01002806 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02002807 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
2808
Willy Tarreau93893792009-07-23 13:19:11 +02002809 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002810 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002811 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02002812 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2813 goto out;
2814
Willy Tarreaubaaee002006-06-26 02:48:02 +02002815 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
2816 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
2817 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
2818 else {
2819 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
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 }
2823 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002824 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002825 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002826
2827 if (curproxy == &defproxy) {
2828 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2829 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002830 err_code |= ERR_ALERT | ERR_FATAL;
2831 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002832 }
2833
William Lallemanddf1425a2015-04-28 20:17:49 +02002834 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2835 goto out;
2836
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002837 if (!*args[1]) {
2838 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
2839 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002840 err_code |= ERR_ALERT | ERR_FATAL;
2841 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002842 }
2843
2844 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002845 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02002846 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002847
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002848 if (curproxy->uuid <= 0) {
2849 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002850 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002851 err_code |= ERR_ALERT | ERR_FATAL;
2852 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002853 }
2854
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002855 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
2856 if (node) {
2857 struct proxy *target = container_of(node, struct proxy, conf.id);
2858 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
2859 file, linenum, proxy_type_str(curproxy), curproxy->id,
2860 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
2861 err_code |= ERR_ALERT | ERR_FATAL;
2862 goto out;
2863 }
2864 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01002865 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002866 else if (!strcmp(args[0], "description")) {
2867 int i, len=0;
2868 char *d;
2869
Cyril Bonté99ed3272010-01-24 23:29:44 +01002870 if (curproxy == &defproxy) {
2871 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
2872 file, linenum, args[0]);
2873 err_code |= ERR_ALERT | ERR_FATAL;
2874 goto out;
2875 }
2876
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002877 if (!*args[1]) {
2878 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
2879 file, linenum, args[0]);
2880 return -1;
2881 }
2882
Willy Tarreau348acfe2014-04-14 15:00:39 +02002883 for (i = 1; *args[i]; i++)
2884 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002885
2886 d = (char *)calloc(1, len);
2887 curproxy->desc = d;
2888
Willy Tarreau348acfe2014-04-14 15:00:39 +02002889 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
2890 for (i = 2; *args[i]; i++)
2891 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02002892
2893 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002894 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02002895 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2896 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002897 curproxy->state = PR_STSTOPPED;
2898 }
2899 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02002900 if (alertif_too_many_args(0, file, linenum, args, &err_code))
2901 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002902 curproxy->state = PR_STNEW;
2903 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002904 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
2905 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002906 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002907
2908 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002909 unsigned int low, high;
2910
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002911 if (strcmp(args[cur_arg], "all") == 0) {
2912 set = 0;
2913 break;
2914 }
2915 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002916 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002917 }
2918 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002919 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002920 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01002921 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01002922 char *dash = strchr(args[cur_arg], '-');
2923
2924 low = high = str2uic(args[cur_arg]);
2925 if (dash)
2926 high = str2uic(dash + 1);
2927
2928 if (high < low) {
2929 unsigned int swap = low;
2930 low = high;
2931 high = swap;
2932 }
2933
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002934 if (low < 1 || high > LONGBITS) {
2935 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
2936 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02002937 err_code |= ERR_ALERT | ERR_FATAL;
2938 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002939 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01002940 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002941 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002942 }
2943 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01002944 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
2945 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01002946 err_code |= ERR_ALERT | ERR_FATAL;
2947 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002948 }
2949 cur_arg++;
2950 }
2951 curproxy->bind_proc = set;
2952 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002953 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02002954 if (curproxy == &defproxy) {
2955 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002956 err_code |= ERR_ALERT | ERR_FATAL;
2957 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02002958 }
2959
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002960 err = invalid_char(args[1]);
2961 if (err) {
2962 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
2963 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002964 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002965 }
2966
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01002967 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002968 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
2969 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02002970 err_code |= ERR_ALERT | ERR_FATAL;
2971 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02002972 }
2973 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002974 else if (!strcmp(args[0], "cookie")) { /* cookie name */
2975 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002976
Willy Tarreau977b8e42006-12-29 14:19:17 +01002977 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002978 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002979
Willy Tarreaubaaee002006-06-26 02:48:02 +02002980 if (*(args[1]) == 0) {
2981 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
2982 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002983 err_code |= ERR_ALERT | ERR_FATAL;
2984 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002985 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02002986
Willy Tarreau67402132012-05-31 20:40:20 +02002987 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002988 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002989 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02002990 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 curproxy->cookie_name = strdup(args[1]);
2992 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02002993
Willy Tarreaubaaee002006-06-26 02:48:02 +02002994 cur_arg = 2;
2995 while (*(args[cur_arg])) {
2996 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02002997 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002998 }
2999 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003000 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003001 }
3002 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003003 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003004 }
3005 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003006 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003007 }
3008 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003009 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003010 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003011 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003012 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003013 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003014 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003015 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003016 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003017 else if (!strcmp(args[cur_arg], "httponly")) {
3018 curproxy->ck_opts |= PR_CK_HTTPONLY;
3019 }
3020 else if (!strcmp(args[cur_arg], "secure")) {
3021 curproxy->ck_opts |= PR_CK_SECURE;
3022 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003023 else if (!strcmp(args[cur_arg], "domain")) {
3024 if (!*args[cur_arg + 1]) {
3025 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3026 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003027 err_code |= ERR_ALERT | ERR_FATAL;
3028 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003029 }
3030
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003031 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003032 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003033 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3034 " dots nor does not start with a dot."
3035 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003036 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003037 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003038 }
3039
3040 err = invalid_domainchar(args[cur_arg + 1]);
3041 if (err) {
3042 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3043 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003044 err_code |= ERR_ALERT | ERR_FATAL;
3045 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003046 }
3047
Willy Tarreau68a897b2009-12-03 23:28:34 +01003048 if (!curproxy->cookie_domain) {
3049 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3050 } else {
3051 /* one domain was already specified, add another one by
3052 * building the string which will be returned along with
3053 * the cookie.
3054 */
3055 char *new_ptr;
3056 int new_len = strlen(curproxy->cookie_domain) +
3057 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3058 new_ptr = malloc(new_len);
3059 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3060 free(curproxy->cookie_domain);
3061 curproxy->cookie_domain = new_ptr;
3062 }
Willy Tarreau31936852010-10-06 16:59:56 +02003063 cur_arg++;
3064 }
3065 else if (!strcmp(args[cur_arg], "maxidle")) {
3066 unsigned int maxidle;
3067 const char *res;
3068
3069 if (!*args[cur_arg + 1]) {
3070 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3071 file, linenum, args[cur_arg]);
3072 err_code |= ERR_ALERT | ERR_FATAL;
3073 goto out;
3074 }
3075
3076 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3077 if (res) {
3078 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3079 file, linenum, *res, args[cur_arg]);
3080 err_code |= ERR_ALERT | ERR_FATAL;
3081 goto out;
3082 }
3083 curproxy->cookie_maxidle = maxidle;
3084 cur_arg++;
3085 }
3086 else if (!strcmp(args[cur_arg], "maxlife")) {
3087 unsigned int maxlife;
3088 const char *res;
3089
3090 if (!*args[cur_arg + 1]) {
3091 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3092 file, linenum, args[cur_arg]);
3093 err_code |= ERR_ALERT | ERR_FATAL;
3094 goto out;
3095 }
3096
3097 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3098 if (res) {
3099 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3100 file, linenum, *res, args[cur_arg]);
3101 err_code |= ERR_ALERT | ERR_FATAL;
3102 goto out;
3103 }
3104 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003105 cur_arg++;
3106 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003108 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 +02003109 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003110 err_code |= ERR_ALERT | ERR_FATAL;
3111 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003112 }
3113 cur_arg++;
3114 }
Willy Tarreau67402132012-05-31 20:40:20 +02003115 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003116 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3117 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003118 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003119 }
3120
Willy Tarreau67402132012-05-31 20:40:20 +02003121 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003122 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3123 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003124 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003125 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003126
Willy Tarreau67402132012-05-31 20:40:20 +02003127 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003128 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3129 file, linenum);
3130 err_code |= ERR_ALERT | ERR_FATAL;
3131 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003132 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003133 else if (!strcmp(args[0], "email-alert")) {
3134 if (*(args[1]) == 0) {
3135 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3136 file, linenum, args[0]);
3137 err_code |= ERR_ALERT | ERR_FATAL;
3138 goto out;
3139 }
3140
3141 if (!strcmp(args[1], "from")) {
3142 if (*(args[1]) == 0) {
3143 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3144 file, linenum, args[1]);
3145 err_code |= ERR_ALERT | ERR_FATAL;
3146 goto out;
3147 }
3148 free(curproxy->email_alert.from);
3149 curproxy->email_alert.from = strdup(args[2]);
3150 }
3151 else if (!strcmp(args[1], "mailers")) {
3152 if (*(args[1]) == 0) {
3153 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3154 file, linenum, args[1]);
3155 err_code |= ERR_ALERT | ERR_FATAL;
3156 goto out;
3157 }
3158 free(curproxy->email_alert.mailers.name);
3159 curproxy->email_alert.mailers.name = strdup(args[2]);
3160 }
3161 else if (!strcmp(args[1], "myhostname")) {
3162 if (*(args[1]) == 0) {
3163 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3164 file, linenum, args[1]);
3165 err_code |= ERR_ALERT | ERR_FATAL;
3166 goto out;
3167 }
3168 free(curproxy->email_alert.myhostname);
3169 curproxy->email_alert.myhostname = strdup(args[2]);
3170 }
Simon Horman64e34162015-02-06 11:11:57 +09003171 else if (!strcmp(args[1], "level")) {
3172 curproxy->email_alert.level = get_log_level(args[2]);
3173 if (curproxy->email_alert.level < 0) {
3174 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3175 file, linenum, args[1], args[2]);
3176 err_code |= ERR_ALERT | ERR_FATAL;
3177 goto out;
3178 }
3179 }
Simon Horman9dc49962015-01-30 11:22:59 +09003180 else if (!strcmp(args[1], "to")) {
3181 if (*(args[1]) == 0) {
3182 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3183 file, linenum, args[1]);
3184 err_code |= ERR_ALERT | ERR_FATAL;
3185 goto out;
3186 }
3187 free(curproxy->email_alert.to);
3188 curproxy->email_alert.to = strdup(args[2]);
3189 }
3190 else {
3191 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3192 file, linenum, args[1]);
3193 err_code |= ERR_ALERT | ERR_FATAL;
3194 goto out;
3195 }
Simon Horman64e34162015-02-06 11:11:57 +09003196 /* Indicate that the email_alert is at least partially configured */
3197 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003198 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003199 else if (!strcmp(args[0], "external-check")) {
3200 if (*(args[1]) == 0) {
3201 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3202 file, linenum, args[0]);
3203 err_code |= ERR_ALERT | ERR_FATAL;
3204 goto out;
3205 }
3206
3207 if (!strcmp(args[1], "command")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003208 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3209 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003210 if (*(args[1]) == 0) {
3211 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3212 file, linenum, args[1]);
3213 err_code |= ERR_ALERT | ERR_FATAL;
3214 goto out;
3215 }
3216 free(curproxy->check_command);
3217 curproxy->check_command = strdup(args[2]);
3218 }
3219 else if (!strcmp(args[1], "path")) {
William Lallemanddf1425a2015-04-28 20:17:49 +02003220 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3221 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09003222 if (*(args[1]) == 0) {
3223 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3224 file, linenum, args[1]);
3225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
3227 }
3228 free(curproxy->check_path);
3229 curproxy->check_path = strdup(args[2]);
3230 }
3231 else {
3232 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3233 file, linenum, args[1]);
3234 err_code |= ERR_ALERT | ERR_FATAL;
3235 goto out;
3236 }
3237 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003238 else if (!strcmp(args[0], "persist")) { /* persist */
3239 if (*(args[1]) == 0) {
3240 Alert("parsing [%s:%d] : missing persist method.\n",
3241 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003242 err_code |= ERR_ALERT | ERR_FATAL;
3243 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003244 }
3245
3246 if (!strncmp(args[1], "rdp-cookie", 10)) {
3247 curproxy->options2 |= PR_O2_RDPC_PRST;
3248
Emeric Brunb982a3d2010-01-04 15:45:53 +01003249 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003250 const char *beg, *end;
3251
3252 beg = args[1] + 11;
3253 end = strchr(beg, ')');
3254
William Lallemanddf1425a2015-04-28 20:17:49 +02003255 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3256 goto out;
3257
Emeric Brun647caf12009-06-30 17:57:00 +02003258 if (!end || end == beg) {
3259 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3260 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003261 err_code |= ERR_ALERT | ERR_FATAL;
3262 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003263 }
3264
3265 free(curproxy->rdp_cookie_name);
3266 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3267 curproxy->rdp_cookie_len = end-beg;
3268 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003269 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003270 free(curproxy->rdp_cookie_name);
3271 curproxy->rdp_cookie_name = strdup("msts");
3272 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3273 }
3274 else { /* syntax */
3275 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3276 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003277 err_code |= ERR_ALERT | ERR_FATAL;
3278 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003279 }
3280 }
3281 else {
3282 Alert("parsing [%s:%d] : unknown persist method.\n",
3283 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003284 err_code |= ERR_ALERT | ERR_FATAL;
3285 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003286 }
3287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003288 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003289 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003290
Cyril Bonté3b7a3692010-01-10 17:01:47 +01003291 if (curproxy == &defproxy) {
3292 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295 }
3296
Willy Tarreau977b8e42006-12-29 14:19:17 +01003297 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003298 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003299
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 if (*(args[5]) == 0) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003301 Alert("parsing [%s:%d] : '%s' expects 'appsession' <cookie_name> 'len' <len> 'timeout' <timeout> [options*].\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003302 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003303 err_code |= ERR_ALERT | ERR_FATAL;
3304 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003305 }
3306 have_appsession = 1;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003307 free(curproxy->appsession_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003308 curproxy->appsession_name = strdup(args[1]);
3309 curproxy->appsession_name_len = strlen(curproxy->appsession_name);
3310 curproxy->appsession_len = atoi(args[3]);
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003311 err = parse_time_err(args[5], &val, TIME_UNIT_MS);
3312 if (err) {
3313 Alert("parsing [%s:%d] : unexpected character '%c' in %s timeout.\n",
3314 file, linenum, *err, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003315 err_code |= ERR_ALERT | ERR_FATAL;
3316 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01003317 }
Willy Tarreau0c303ee2008-07-07 00:09:58 +02003318 curproxy->timeout.appsession = val;
Willy Tarreauee991362007-05-14 14:37:50 +02003319
Willy Tarreau51041c72007-09-09 21:56:53 +02003320 if (appsession_hash_init(&(curproxy->htbl_proxy), destroy) == 0) {
3321 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003322 err_code |= ERR_ALERT | ERR_ABORT;
3323 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003324 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003325
3326 cur_arg = 6;
3327 curproxy->options2 &= ~PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003328 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3329 curproxy->options2 |= PR_O2_AS_M_PP;
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003330 while (*(args[cur_arg])) {
Cyril Bontéb21570a2009-11-29 20:04:48 +01003331 if (!strcmp(args[cur_arg], "request-learn")) {
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003332 curproxy->options2 |= PR_O2_AS_REQL;
Cyril Bontéb21570a2009-11-29 20:04:48 +01003333 } else if (!strcmp(args[cur_arg], "prefix")) {
3334 curproxy->options2 |= PR_O2_AS_PFX;
3335 } else if (!strcmp(args[cur_arg], "mode")) {
3336 if (!*args[cur_arg + 1]) {
3337 Alert("parsing [%s:%d] : '%s': missing argument for '%s'.\n",
3338 file, linenum, args[0], args[cur_arg]);
3339 err_code |= ERR_ALERT | ERR_FATAL;
3340 goto out;
3341 }
3342
3343 cur_arg++;
3344 if (!strcmp(args[cur_arg], "query-string")) {
3345 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3346 curproxy->options2 |= PR_O2_AS_M_QS;
3347 } else if (!strcmp(args[cur_arg], "path-parameters")) {
3348 curproxy->options2 &= ~PR_O2_AS_M_ANY;
3349 curproxy->options2 |= PR_O2_AS_M_PP;
3350 } else {
3351 Alert("parsing [%s:%d] : unknown mode '%s'\n", file, linenum, args[cur_arg]);
3352 err_code |= ERR_ALERT | ERR_FATAL;
3353 goto out;
3354 }
3355 }
Cyril Bontébf47aeb2009-10-15 00:15:40 +02003356 cur_arg++;
3357 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003358 } /* Url App Session */
3359 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003360 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003361 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003362
Willy Tarreaubaaee002006-06-26 02:48:02 +02003363 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003364 if (curproxy == &defproxy) {
3365 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
3368 }
3369
William Lallemand1a748ae2015-05-19 16:37:23 +02003370 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3371 goto out;
3372
Willy Tarreaubaaee002006-06-26 02:48:02 +02003373 if (*(args[4]) == 0) {
3374 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3375 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003379 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003380 curproxy->capture_name = strdup(args[2]);
3381 curproxy->capture_namelen = strlen(curproxy->capture_name);
3382 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003383 curproxy->to_log |= LW_COOKIE;
3384 }
3385 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3386 struct cap_hdr *hdr;
3387
3388 if (curproxy == &defproxy) {
3389 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 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003392 }
3393
William Lallemand1a748ae2015-05-19 16:37:23 +02003394 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3395 goto out;
3396
Willy Tarreaubaaee002006-06-26 02:48:02 +02003397 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3398 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3399 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003400 err_code |= ERR_ALERT | ERR_FATAL;
3401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003402 }
3403
3404 hdr = calloc(sizeof(struct cap_hdr), 1);
3405 hdr->next = curproxy->req_cap;
3406 hdr->name = strdup(args[3]);
3407 hdr->namelen = strlen(args[3]);
3408 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003409 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003410 hdr->index = curproxy->nb_req_cap++;
3411 curproxy->req_cap = hdr;
3412 curproxy->to_log |= LW_REQHDR;
3413 }
3414 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3415 struct cap_hdr *hdr;
3416
3417 if (curproxy == &defproxy) {
3418 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 +02003419 err_code |= ERR_ALERT | ERR_FATAL;
3420 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
3422
William Lallemand1a748ae2015-05-19 16:37:23 +02003423 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3424 goto out;
3425
Willy Tarreaubaaee002006-06-26 02:48:02 +02003426 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3427 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3428 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003429 err_code |= ERR_ALERT | ERR_FATAL;
3430 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 }
3432 hdr = calloc(sizeof(struct cap_hdr), 1);
3433 hdr->next = curproxy->rsp_cap;
3434 hdr->name = strdup(args[3]);
3435 hdr->namelen = strlen(args[3]);
3436 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003437 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003438 hdr->index = curproxy->nb_rsp_cap++;
3439 curproxy->rsp_cap = hdr;
3440 curproxy->to_log |= LW_RSPHDR;
3441 }
3442 else {
3443 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3444 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003445 err_code |= ERR_ALERT | ERR_FATAL;
3446 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003447 }
3448 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003449 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003450 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003451 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003452
William Lallemanddf1425a2015-04-28 20:17:49 +02003453 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3454 goto out;
3455
Willy Tarreaubaaee002006-06-26 02:48:02 +02003456 if (*(args[1]) == 0) {
3457 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3458 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003459 err_code |= ERR_ALERT | ERR_FATAL;
3460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003461 }
3462 curproxy->conn_retries = atol(args[1]);
3463 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003464 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01003465 struct http_req_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003466
3467 if (curproxy == &defproxy) {
3468 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3469 err_code |= ERR_ALERT | ERR_FATAL;
3470 goto out;
3471 }
3472
Willy Tarreau20b0de52012-12-24 15:45:22 +01003473 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
3474 !LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->cond &&
3475 (LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_ALLOW ||
3476 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_DENY ||
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003477 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_REDIR ||
Willy Tarreau20b0de52012-12-24 15:45:22 +01003478 LIST_PREV(&curproxy->http_req_rules, struct http_req_rule *, list)->action == HTTP_REQ_ACT_AUTH)) {
3479 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 +01003480 file, linenum, args[0]);
3481 err_code |= ERR_WARN;
3482 }
3483
Willy Tarreauff011f22011-01-06 17:51:27 +01003484 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003485
Willy Tarreauff011f22011-01-06 17:51:27 +01003486 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003487 err_code |= ERR_ALERT | ERR_ABORT;
3488 goto out;
3489 }
3490
Willy Tarreau5002f572014-04-23 01:32:02 +02003491 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003492 err_code |= warnif_cond_conflicts(rule->cond,
3493 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3494 file, linenum);
3495
Willy Tarreauff011f22011-01-06 17:51:27 +01003496 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003497 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003498 else if (!strcmp(args[0], "http-response")) { /* response access control */
3499 struct http_res_rule *rule;
3500
3501 if (curproxy == &defproxy) {
3502 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3503 err_code |= ERR_ALERT | ERR_FATAL;
3504 goto out;
3505 }
3506
3507 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
3508 !LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->cond &&
3509 (LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_ALLOW ||
3510 LIST_PREV(&curproxy->http_res_rules, struct http_res_rule *, list)->action == HTTP_RES_ACT_DENY)) {
3511 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3512 file, linenum, args[0]);
3513 err_code |= ERR_WARN;
3514 }
3515
3516 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3517
3518 if (!rule) {
3519 err_code |= ERR_ALERT | ERR_ABORT;
3520 goto out;
3521 }
3522
3523 err_code |= warnif_cond_conflicts(rule->cond,
3524 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3525 file, linenum);
3526
3527 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3528 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003529 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3530 /* set the header name and length into the proxy structure */
3531 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3532 err_code |= ERR_WARN;
3533
3534 if (!*args[1]) {
3535 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3536 file, linenum, args[0]);
3537 err_code |= ERR_ALERT | ERR_FATAL;
3538 goto out;
3539 }
3540
3541 /* set the desired header name */
3542 free(curproxy->server_id_hdr_name);
3543 curproxy->server_id_hdr_name = strdup(args[1]);
3544 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3545 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003546 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003547 struct http_req_rule *rule;
3548
Willy Tarreaub099aca2008-10-12 17:26:37 +02003549 if (curproxy == &defproxy) {
3550 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003553 }
3554
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003555 /* emulate "block" using "http-request block". Since these rules are supposed to
3556 * be processed before all http-request rules, we put them into their own list
3557 * and will insert them at the end.
3558 */
3559 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3560 if (!rule) {
3561 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003562 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003563 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003564 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3565 err_code |= warnif_cond_conflicts(rule->cond,
3566 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3567 file, linenum);
3568 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003569
3570 if (!already_warned(WARN_BLOCK_DEPRECATED))
3571 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]);
3572
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003573 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003574 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003575 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003576
Cyril Bonté99ed3272010-01-24 23:29:44 +01003577 if (curproxy == &defproxy) {
3578 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3579 err_code |= ERR_ALERT | ERR_FATAL;
3580 goto out;
3581 }
3582
Willy Tarreaube4653b2015-05-28 15:26:58 +02003583 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003584 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3585 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003588 }
3589
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003590 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003591 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003592 err_code |= warnif_cond_conflicts(rule->cond,
3593 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3594 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003595 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003596 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003597 struct switching_rule *rule;
3598
Willy Tarreaub099aca2008-10-12 17:26:37 +02003599 if (curproxy == &defproxy) {
3600 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003601 err_code |= ERR_ALERT | ERR_FATAL;
3602 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003603 }
3604
Willy Tarreau55ea7572007-06-17 19:56:27 +02003605 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003606 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003607
3608 if (*(args[1]) == 0) {
3609 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003610 err_code |= ERR_ALERT | ERR_FATAL;
3611 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003612 }
3613
Willy Tarreauf51658d2014-04-23 01:21:56 +02003614 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3615 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3616 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3617 file, linenum, errmsg);
3618 err_code |= ERR_ALERT | ERR_FATAL;
3619 goto out;
3620 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003621
Willy Tarreauf51658d2014-04-23 01:21:56 +02003622 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003623 }
3624
3625 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3626 rule->cond = cond;
3627 rule->be.name = strdup(args[1]);
3628 LIST_INIT(&rule->list);
3629 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3630 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003631 else if (strcmp(args[0], "use-server") == 0) {
3632 struct server_rule *rule;
3633
3634 if (curproxy == &defproxy) {
3635 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3636 err_code |= ERR_ALERT | ERR_FATAL;
3637 goto out;
3638 }
3639
3640 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3641 err_code |= ERR_WARN;
3642
3643 if (*(args[1]) == 0) {
3644 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
3647 }
3648
3649 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3650 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3651 file, linenum, args[0]);
3652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
3654 }
3655
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003656 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3657 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3658 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003659 err_code |= ERR_ALERT | ERR_FATAL;
3660 goto out;
3661 }
3662
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003663 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003664
3665 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3666 rule->cond = cond;
3667 rule->srv.name = strdup(args[1]);
3668 LIST_INIT(&rule->list);
3669 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3670 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3671 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003672 else if ((!strcmp(args[0], "force-persist")) ||
3673 (!strcmp(args[0], "ignore-persist"))) {
3674 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003675
3676 if (curproxy == &defproxy) {
3677 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3678 err_code |= ERR_ALERT | ERR_FATAL;
3679 goto out;
3680 }
3681
3682 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3683 err_code |= ERR_WARN;
3684
Willy Tarreauef6494c2010-01-28 17:12:36 +01003685 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003686 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3687 file, linenum, args[0]);
3688 err_code |= ERR_ALERT | ERR_FATAL;
3689 goto out;
3690 }
3691
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003692 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3693 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3694 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
3697 }
3698
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003699 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3700 * where force-persist is applied.
3701 */
3702 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003703
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003704 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003705 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003706 if (!strcmp(args[0], "force-persist")) {
3707 rule->type = PERSIST_TYPE_FORCE;
3708 } else {
3709 rule->type = PERSIST_TYPE_IGNORE;
3710 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003711 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003712 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003713 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003714 else if (!strcmp(args[0], "stick-table")) {
3715 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003716 struct proxy *other;
3717
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003718 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003719 if (other) {
3720 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3721 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3722 err_code |= ERR_ALERT | ERR_FATAL;
3723 goto out;
3724 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003725
Emeric Brun32da3c42010-09-23 18:39:19 +02003726 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003727 curproxy->table.type = (unsigned int)-1;
3728 while (*args[myidx]) {
3729 const char *err;
3730
3731 if (strcmp(args[myidx], "size") == 0) {
3732 myidx++;
3733 if (!*(args[myidx])) {
3734 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3735 file, linenum, args[myidx-1]);
3736 err_code |= ERR_ALERT | ERR_FATAL;
3737 goto out;
3738 }
3739 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
3740 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3741 file, linenum, *err, args[myidx-1]);
3742 err_code |= ERR_ALERT | ERR_FATAL;
3743 goto out;
3744 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003745 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003746 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003747 else if (strcmp(args[myidx], "peers") == 0) {
3748 myidx++;
Godbach50523162013-12-11 19:48:57 +08003749 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08003750 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3751 file, linenum, args[myidx-1]);
3752 err_code |= ERR_ALERT | ERR_FATAL;
3753 goto out;
Godbach50523162013-12-11 19:48:57 +08003754 }
Emeric Brun32da3c42010-09-23 18:39:19 +02003755 curproxy->table.peers.name = strdup(args[myidx++]);
3756 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003757 else if (strcmp(args[myidx], "expire") == 0) {
3758 myidx++;
3759 if (!*(args[myidx])) {
3760 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
3761 file, linenum, args[myidx-1]);
3762 err_code |= ERR_ALERT | ERR_FATAL;
3763 goto out;
3764 }
3765 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
3766 if (err) {
3767 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
3768 file, linenum, *err, args[myidx-1]);
3769 err_code |= ERR_ALERT | ERR_FATAL;
3770 goto out;
3771 }
3772 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01003773 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003774 }
3775 else if (strcmp(args[myidx], "nopurge") == 0) {
3776 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01003777 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003778 }
3779 else if (strcmp(args[myidx], "type") == 0) {
3780 myidx++;
3781 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
3782 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
3783 file, linenum, args[myidx]);
3784 err_code |= ERR_ALERT | ERR_FATAL;
3785 goto out;
3786 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003787 /* myidx already points to next arg */
3788 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003789 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02003790 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02003791 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02003792
3793 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003794 nw = args[myidx];
3795 while (*nw) {
3796 /* the "store" keyword supports a comma-separated list */
3797 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02003798 sa = NULL; /* store arg */
3799 while (*nw && *nw != ',') {
3800 if (*nw == '(') {
3801 *nw = 0;
3802 sa = ++nw;
3803 while (*nw != ')') {
3804 if (!*nw) {
3805 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
3806 file, linenum, args[0], cw);
3807 err_code |= ERR_ALERT | ERR_FATAL;
3808 goto out;
3809 }
3810 nw++;
3811 }
3812 *nw = '\0';
3813 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003814 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02003815 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003816 if (*nw)
3817 *nw++ = '\0';
3818 type = stktable_get_data_type(cw);
3819 if (type < 0) {
3820 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
3821 file, linenum, args[0], cw);
3822 err_code |= ERR_ALERT | ERR_FATAL;
3823 goto out;
3824 }
Willy Tarreauac782882010-06-20 10:41:54 +02003825
3826 err = stktable_alloc_data_type(&curproxy->table, type, sa);
3827 switch (err) {
3828 case PE_NONE: break;
3829 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003830 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
3831 file, linenum, args[0], cw);
3832 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02003833 break;
3834
3835 case PE_ARG_MISSING:
3836 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
3837 file, linenum, args[0], cw);
3838 err_code |= ERR_ALERT | ERR_FATAL;
3839 goto out;
3840
3841 case PE_ARG_NOT_USED:
3842 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
3843 file, linenum, args[0], cw);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846
3847 default:
3848 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
3849 file, linenum, args[0], cw);
3850 err_code |= ERR_ALERT | ERR_FATAL;
3851 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02003852 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02003853 }
3854 myidx++;
3855 }
Willy Tarreau0c559312010-01-26 18:36:26 +01003856 else {
3857 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
3858 file, linenum, args[myidx]);
3859 err_code |= ERR_ALERT | ERR_FATAL;
3860 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003861 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003862 }
3863
3864 if (!curproxy->table.size) {
3865 Alert("parsing [%s:%d] : stick-table: missing size.\n",
3866 file, linenum);
3867 err_code |= ERR_ALERT | ERR_FATAL;
3868 goto out;
3869 }
3870
3871 if (curproxy->table.type == (unsigned int)-1) {
3872 Alert("parsing [%s:%d] : stick-table: missing type.\n",
3873 file, linenum);
3874 err_code |= ERR_ALERT | ERR_FATAL;
3875 goto out;
3876 }
3877 }
3878 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01003879 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02003880 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01003881 int myidx = 0;
3882 const char *name = NULL;
3883 int flags;
3884
3885 if (curproxy == &defproxy) {
3886 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3887 err_code |= ERR_ALERT | ERR_FATAL;
3888 goto out;
3889 }
3890
3891 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
3892 err_code |= ERR_WARN;
3893 goto out;
3894 }
3895
3896 myidx++;
3897 if ((strcmp(args[myidx], "store") == 0) ||
3898 (strcmp(args[myidx], "store-request") == 0)) {
3899 myidx++;
3900 flags = STK_IS_STORE;
3901 }
3902 else if (strcmp(args[myidx], "store-response") == 0) {
3903 myidx++;
3904 flags = STK_IS_STORE | STK_ON_RSP;
3905 }
3906 else if (strcmp(args[myidx], "match") == 0) {
3907 myidx++;
3908 flags = STK_IS_MATCH;
3909 }
3910 else if (strcmp(args[myidx], "on") == 0) {
3911 myidx++;
3912 flags = STK_IS_MATCH | STK_IS_STORE;
3913 }
3914 else {
3915 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
3916 err_code |= ERR_ALERT | ERR_FATAL;
3917 goto out;
3918 }
3919
3920 if (*(args[myidx]) == 0) {
3921 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
3922 err_code |= ERR_ALERT | ERR_FATAL;
3923 goto out;
3924 }
3925
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003926 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01003927 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003928 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01003929 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003930 err_code |= ERR_ALERT | ERR_FATAL;
3931 goto out;
3932 }
3933
3934 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01003935 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
3936 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
3937 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003938 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003939 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003940 goto out;
3941 }
3942 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01003943 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
3944 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
3945 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01003946 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003947 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003948 goto out;
3949 }
3950 }
3951
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003952 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01003953 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02003954
Emeric Brunb982a3d2010-01-04 15:45:53 +01003955 if (strcmp(args[myidx], "table") == 0) {
3956 myidx++;
3957 name = args[myidx++];
3958 }
3959
Willy Tarreauef6494c2010-01-28 17:12:36 +01003960 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003961 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
3962 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
3963 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003964 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003965 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01003966 goto out;
3967 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003968 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01003969 else if (*(args[myidx])) {
3970 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
3971 file, linenum, args[0], args[myidx]);
3972 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09003973 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01003974 goto out;
3975 }
Emeric Brun97679e72010-09-23 17:56:44 +02003976 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003977 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02003978 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003979 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01003980
Emeric Brunb982a3d2010-01-04 15:45:53 +01003981 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
3982 rule->cond = cond;
3983 rule->expr = expr;
3984 rule->flags = flags;
3985 rule->table.name = name ? strdup(name) : NULL;
3986 LIST_INIT(&rule->list);
3987 if (flags & STK_ON_RSP)
3988 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
3989 else
3990 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
3991 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003992 else if (!strcmp(args[0], "stats")) {
3993 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
3994 curproxy->uri_auth = NULL; /* we must detach from the default config */
3995
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01003996 if (!*args[1]) {
3997 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02003998 } else if (!strcmp(args[1], "admin")) {
3999 struct stats_admin_rule *rule;
4000
4001 if (curproxy == &defproxy) {
4002 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4003 err_code |= ERR_ALERT | ERR_FATAL;
4004 goto out;
4005 }
4006
4007 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4008 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4009 err_code |= ERR_ALERT | ERR_ABORT;
4010 goto out;
4011 }
4012
4013 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4014 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4015 file, linenum, args[0], args[1]);
4016 err_code |= ERR_ALERT | ERR_FATAL;
4017 goto out;
4018 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004019 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4020 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4021 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004022 err_code |= ERR_ALERT | ERR_FATAL;
4023 goto out;
4024 }
4025
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004026 err_code |= warnif_cond_conflicts(cond,
4027 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4028 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004029
4030 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4031 rule->cond = cond;
4032 LIST_INIT(&rule->list);
4033 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004034 } else if (!strcmp(args[1], "uri")) {
4035 if (*(args[2]) == 0) {
4036 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004037 err_code |= ERR_ALERT | ERR_FATAL;
4038 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004039 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4040 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004041 err_code |= ERR_ALERT | ERR_ABORT;
4042 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004043 }
4044 } else if (!strcmp(args[1], "realm")) {
4045 if (*(args[2]) == 0) {
4046 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004047 err_code |= ERR_ALERT | ERR_FATAL;
4048 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004049 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4050 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004051 err_code |= ERR_ALERT | ERR_ABORT;
4052 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004053 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004054 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004055 unsigned interval;
4056
4057 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4058 if (err) {
4059 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4060 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004061 err_code |= ERR_ALERT | ERR_FATAL;
4062 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004063 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4064 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004065 err_code |= ERR_ALERT | ERR_ABORT;
4066 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004067 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004068 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Willy Tarreauff011f22011-01-06 17:51:27 +01004069 struct http_req_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004070
4071 if (curproxy == &defproxy) {
4072 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4073 err_code |= ERR_ALERT | ERR_FATAL;
4074 goto out;
4075 }
4076
4077 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4078 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4079 err_code |= ERR_ALERT | ERR_ABORT;
4080 goto out;
4081 }
4082
Willy Tarreauff011f22011-01-06 17:51:27 +01004083 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
4084 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct http_req_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004085 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4086 file, linenum, args[0]);
4087 err_code |= ERR_WARN;
4088 }
4089
Willy Tarreauff011f22011-01-06 17:51:27 +01004090 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004091
Willy Tarreauff011f22011-01-06 17:51:27 +01004092 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004093 err_code |= ERR_ALERT | ERR_ABORT;
4094 goto out;
4095 }
4096
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004097 err_code |= warnif_cond_conflicts(rule->cond,
4098 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4099 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004100 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004101
Willy Tarreaubaaee002006-06-26 02:48:02 +02004102 } else if (!strcmp(args[1], "auth")) {
4103 if (*(args[2]) == 0) {
4104 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004105 err_code |= ERR_ALERT | ERR_FATAL;
4106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004107 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4108 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004109 err_code |= ERR_ALERT | ERR_ABORT;
4110 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004111 }
4112 } else if (!strcmp(args[1], "scope")) {
4113 if (*(args[2]) == 0) {
4114 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004115 err_code |= ERR_ALERT | ERR_FATAL;
4116 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004117 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4118 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004119 err_code |= ERR_ALERT | ERR_ABORT;
4120 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004121 }
4122 } else if (!strcmp(args[1], "enable")) {
4123 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4124 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004125 err_code |= ERR_ALERT | ERR_ABORT;
4126 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004127 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004128 } else if (!strcmp(args[1], "hide-version")) {
4129 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4130 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004131 err_code |= ERR_ALERT | ERR_ABORT;
4132 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004133 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004134 } else if (!strcmp(args[1], "show-legends")) {
4135 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4136 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4137 err_code |= ERR_ALERT | ERR_ABORT;
4138 goto out;
4139 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004140 } else if (!strcmp(args[1], "show-node")) {
4141
4142 if (*args[2]) {
4143 int i;
4144 char c;
4145
4146 for (i=0; args[2][i]; i++) {
4147 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004148 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4149 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004150 break;
4151 }
4152
4153 if (!i || args[2][i]) {
4154 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4155 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4156 file, linenum, args[0], args[1]);
4157 err_code |= ERR_ALERT | ERR_FATAL;
4158 goto out;
4159 }
4160 }
4161
4162 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4163 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4164 err_code |= ERR_ALERT | ERR_ABORT;
4165 goto out;
4166 }
4167 } else if (!strcmp(args[1], "show-desc")) {
4168 char *desc = NULL;
4169
4170 if (*args[2]) {
4171 int i, len=0;
4172 char *d;
4173
Willy Tarreau348acfe2014-04-14 15:00:39 +02004174 for (i = 2; *args[i]; i++)
4175 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004176
4177 desc = d = (char *)calloc(1, len);
4178
Willy Tarreau348acfe2014-04-14 15:00:39 +02004179 d += snprintf(d, desc + len - d, "%s", args[2]);
4180 for (i = 3; *args[i]; i++)
4181 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004182 }
4183
4184 if (!*args[2] && !global.desc)
4185 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4186 file, linenum, args[1]);
4187 else {
4188 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4189 free(desc);
4190 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4191 err_code |= ERR_ALERT | ERR_ABORT;
4192 goto out;
4193 }
4194 free(desc);
4195 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004196 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004197stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004198 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 +01004199 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004202 }
4203 }
4204 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004205 int optnum;
4206
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004207 if (*(args[1]) == '\0') {
4208 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4209 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004210 err_code |= ERR_ALERT | ERR_FATAL;
4211 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004212 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004213
4214 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4215 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004216 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4217 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4218 file, linenum, cfg_opts[optnum].name);
4219 err_code |= ERR_ALERT | ERR_FATAL;
4220 goto out;
4221 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004222 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4223 goto out;
4224
Willy Tarreau93893792009-07-23 13:19:11 +02004225 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4226 err_code |= ERR_WARN;
4227 goto out;
4228 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004229
Willy Tarreau3842f002009-06-14 11:39:52 +02004230 curproxy->no_options &= ~cfg_opts[optnum].val;
4231 curproxy->options &= ~cfg_opts[optnum].val;
4232
4233 switch (kwm) {
4234 case KWM_STD:
4235 curproxy->options |= cfg_opts[optnum].val;
4236 break;
4237 case KWM_NO:
4238 curproxy->no_options |= cfg_opts[optnum].val;
4239 break;
4240 case KWM_DEF: /* already cleared */
4241 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004242 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004243
Willy Tarreau93893792009-07-23 13:19:11 +02004244 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004245 }
4246 }
4247
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004248 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4249 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004250 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4251 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4252 file, linenum, cfg_opts2[optnum].name);
4253 err_code |= ERR_ALERT | ERR_FATAL;
4254 goto out;
4255 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004256 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4257 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004258 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4259 err_code |= ERR_WARN;
4260 goto out;
4261 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004262
Willy Tarreau3842f002009-06-14 11:39:52 +02004263 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4264 curproxy->options2 &= ~cfg_opts2[optnum].val;
4265
4266 switch (kwm) {
4267 case KWM_STD:
4268 curproxy->options2 |= cfg_opts2[optnum].val;
4269 break;
4270 case KWM_NO:
4271 curproxy->no_options2 |= cfg_opts2[optnum].val;
4272 break;
4273 case KWM_DEF: /* already cleared */
4274 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004275 }
Willy Tarreau93893792009-07-23 13:19:11 +02004276 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004277 }
4278 }
4279
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004280 /* HTTP options override each other. They can be cancelled using
4281 * "no option xxx" which only switches to default mode if the mode
4282 * was this one (useful for cancelling options set in defaults
4283 * sections).
4284 */
4285 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004286 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4287 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004288 if (kwm == KWM_STD) {
4289 curproxy->options &= ~PR_O_HTTP_MODE;
4290 curproxy->options |= PR_O_HTTP_PCL;
4291 goto out;
4292 }
4293 else if (kwm == KWM_NO) {
4294 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4295 curproxy->options &= ~PR_O_HTTP_MODE;
4296 goto out;
4297 }
4298 }
4299 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004300 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4301 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004302 if (kwm == KWM_STD) {
4303 curproxy->options &= ~PR_O_HTTP_MODE;
4304 curproxy->options |= PR_O_HTTP_FCL;
4305 goto out;
4306 }
4307 else if (kwm == KWM_NO) {
4308 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4309 curproxy->options &= ~PR_O_HTTP_MODE;
4310 goto out;
4311 }
4312 }
4313 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004314 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4315 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004316 if (kwm == KWM_STD) {
4317 curproxy->options &= ~PR_O_HTTP_MODE;
4318 curproxy->options |= PR_O_HTTP_SCL;
4319 goto out;
4320 }
4321 else if (kwm == KWM_NO) {
4322 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4323 curproxy->options &= ~PR_O_HTTP_MODE;
4324 goto out;
4325 }
4326 }
4327 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004328 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4329 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004330 if (kwm == KWM_STD) {
4331 curproxy->options &= ~PR_O_HTTP_MODE;
4332 curproxy->options |= PR_O_HTTP_KAL;
4333 goto out;
4334 }
4335 else if (kwm == KWM_NO) {
4336 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4337 curproxy->options &= ~PR_O_HTTP_MODE;
4338 goto out;
4339 }
4340 }
4341 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004342 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4343 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004344 if (kwm == KWM_STD) {
4345 curproxy->options &= ~PR_O_HTTP_MODE;
4346 curproxy->options |= PR_O_HTTP_TUN;
4347 goto out;
4348 }
4349 else if (kwm == KWM_NO) {
4350 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4351 curproxy->options &= ~PR_O_HTTP_MODE;
4352 goto out;
4353 }
4354 }
4355
Joseph Lynch726ab712015-05-11 23:25:34 -07004356 /* Redispatch can take an integer argument that control when the
4357 * resispatch occurs. All values are relative to the retries option.
4358 * This can be cancelled using "no option xxx".
4359 */
4360 if (strcmp(args[1], "redispatch") == 0) {
4361 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4362 err_code |= ERR_WARN;
4363 goto out;
4364 }
4365
4366 curproxy->no_options &= ~PR_O_REDISP;
4367 curproxy->options &= ~PR_O_REDISP;
4368
4369 switch (kwm) {
4370 case KWM_STD:
4371 curproxy->options |= PR_O_REDISP;
4372 curproxy->redispatch_after = -1;
4373 if(*args[2]) {
4374 curproxy->redispatch_after = atol(args[2]);
4375 }
4376 break;
4377 case KWM_NO:
4378 curproxy->no_options |= PR_O_REDISP;
4379 curproxy->redispatch_after = 0;
4380 break;
4381 case KWM_DEF: /* already cleared */
4382 break;
4383 }
4384 goto out;
4385 }
4386
Willy Tarreau3842f002009-06-14 11:39:52 +02004387 if (kwm != KWM_STD) {
4388 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004389 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004390 err_code |= ERR_ALERT | ERR_FATAL;
4391 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004392 }
4393
Emeric Brun3a058f32009-06-30 18:26:00 +02004394 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004395 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004397 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004398 if (*(args[2]) != '\0') {
4399 if (!strcmp(args[2], "clf")) {
4400 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004401 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004402 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004403 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004404 err_code |= ERR_ALERT | ERR_FATAL;
4405 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004406 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004407 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4408 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004409 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004410 if (curproxy->conf.logformat_string != default_http_log_format &&
4411 curproxy->conf.logformat_string != default_tcp_log_format &&
4412 curproxy->conf.logformat_string != clf_http_log_format)
4413 free(curproxy->conf.logformat_string);
4414 curproxy->conf.logformat_string = logformat;
4415
4416 free(curproxy->conf.lfs_file);
4417 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4418 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004419 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004420 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004421 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004422 if (curproxy->conf.logformat_string != default_http_log_format &&
4423 curproxy->conf.logformat_string != default_tcp_log_format &&
4424 curproxy->conf.logformat_string != clf_http_log_format)
4425 free(curproxy->conf.logformat_string);
4426 curproxy->conf.logformat_string = default_tcp_log_format;
4427
4428 free(curproxy->conf.lfs_file);
4429 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4430 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004431
4432 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4433 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004434 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004435 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004436 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004437 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004438 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004439
William Lallemanddf1425a2015-04-28 20:17:49 +02004440 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4441 goto out;
4442
Willy Tarreau13943ab2006-12-31 00:24:10 +01004443 if (curproxy->cap & PR_CAP_FE)
4444 curproxy->options |= PR_O_TCP_CLI_KA;
4445 if (curproxy->cap & PR_CAP_BE)
4446 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004447 }
4448 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004449 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004450 err_code |= ERR_WARN;
4451
Willy Tarreaubaaee002006-06-26 02:48:02 +02004452 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004453 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004454 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004455 curproxy->options2 &= ~PR_O2_CHK_ANY;
4456 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004457 if (!*args[2]) { /* no argument */
4458 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4459 curproxy->check_len = strlen(DEF_CHECK_REQ);
4460 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004461 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004462 curproxy->check_req = (char *)malloc(reqlen);
4463 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004464 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004465 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004466 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004467 if (*args[4])
4468 reqlen += strlen(args[4]);
4469 else
4470 reqlen += strlen("HTTP/1.0");
4471
4472 curproxy->check_req = (char *)malloc(reqlen);
4473 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004474 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004475 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004476 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4477 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004478 }
4479 else if (!strcmp(args[1], "ssl-hello-chk")) {
4480 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004481 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004483
Willy Tarreaua534fea2008-08-03 12:19:50 +02004484 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004485 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004486 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004487 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004488
4489 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4490 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004491 }
Willy Tarreau23677902007-05-08 23:50:35 +02004492 else if (!strcmp(args[1], "smtpchk")) {
4493 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004494 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004495 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004496 curproxy->options2 &= ~PR_O2_CHK_ANY;
4497 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004498
4499 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4500 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4501 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4502 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4503 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4504 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4505 curproxy->check_req = (char *)malloc(reqlen);
4506 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4507 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4508 } else {
4509 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4510 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4511 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4512 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4513 }
4514 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004515 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4516 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004517 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004518 else if (!strcmp(args[1], "pgsql-check")) {
4519 /* use PostgreSQL request to check servers' health */
4520 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4521 err_code |= ERR_WARN;
4522
4523 free(curproxy->check_req);
4524 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004525 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004526 curproxy->options2 |= PR_O2_PGSQL_CHK;
4527
4528 if (*(args[2])) {
4529 int cur_arg = 2;
4530
4531 while (*(args[cur_arg])) {
4532 if (strcmp(args[cur_arg], "user") == 0) {
4533 char * packet;
4534 uint32_t packet_len;
4535 uint32_t pv;
4536
4537 /* suboption header - needs additional argument for it */
4538 if (*(args[cur_arg+1]) == 0) {
4539 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4540 file, linenum, args[0], args[1], args[cur_arg]);
4541 err_code |= ERR_ALERT | ERR_FATAL;
4542 goto out;
4543 }
4544
4545 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4546 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4547 pv = htonl(0x30000); /* protocol version 3.0 */
4548
4549 packet = (char*) calloc(1, packet_len);
4550
4551 memcpy(packet + 4, &pv, 4);
4552
4553 /* copy "user" */
4554 memcpy(packet + 8, "user", 4);
4555
4556 /* copy username */
4557 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4558
4559 free(curproxy->check_req);
4560 curproxy->check_req = packet;
4561 curproxy->check_len = packet_len;
4562
4563 packet_len = htonl(packet_len);
4564 memcpy(packet, &packet_len, 4);
4565 cur_arg += 2;
4566 } else {
4567 /* unknown suboption - catchall */
4568 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4569 file, linenum, args[0], args[1]);
4570 err_code |= ERR_ALERT | ERR_FATAL;
4571 goto out;
4572 }
4573 } /* end while loop */
4574 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004575 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4576 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004577 }
4578
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004579 else if (!strcmp(args[1], "redis-check")) {
4580 /* use REDIS PING request to check servers' health */
4581 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4582 err_code |= ERR_WARN;
4583
4584 free(curproxy->check_req);
4585 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004586 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004587 curproxy->options2 |= PR_O2_REDIS_CHK;
4588
4589 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4590 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4591 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004592
4593 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4594 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004595 }
4596
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004597 else if (!strcmp(args[1], "mysql-check")) {
4598 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004599 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4600 err_code |= ERR_WARN;
4601
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004602 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004603 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004604 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004605 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004606
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004607 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004608 * const char mysql40_client_auth_pkt[] = {
4609 * "\x0e\x00\x00" // packet length
4610 * "\x01" // packet number
4611 * "\x00\x00" // client capabilities
4612 * "\x00\x00\x01" // max packet
4613 * "haproxy\x00" // username (null terminated string)
4614 * "\x00" // filler (always 0x00)
4615 * "\x01\x00\x00" // packet length
4616 * "\x00" // packet number
4617 * "\x01" // COM_QUIT command
4618 * };
4619 */
4620
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004621 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4622 * const char mysql41_client_auth_pkt[] = {
4623 * "\x0e\x00\x00\" // packet length
4624 * "\x01" // packet number
4625 * "\x00\x00\x00\x00" // client capabilities
4626 * "\x00\x00\x00\x01" // max packet
4627 * "\x21" // character set (UTF-8)
4628 * char[23] // All zeroes
4629 * "haproxy\x00" // username (null terminated string)
4630 * "\x00" // filler (always 0x00)
4631 * "\x01\x00\x00" // packet length
4632 * "\x00" // packet number
4633 * "\x01" // COM_QUIT command
4634 * };
4635 */
4636
4637
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004638 if (*(args[2])) {
4639 int cur_arg = 2;
4640
4641 while (*(args[cur_arg])) {
4642 if (strcmp(args[cur_arg], "user") == 0) {
4643 char *mysqluser;
4644 int packetlen, reqlen, userlen;
4645
4646 /* suboption header - needs additional argument for it */
4647 if (*(args[cur_arg+1]) == 0) {
4648 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4649 file, linenum, args[0], args[1], args[cur_arg]);
4650 err_code |= ERR_ALERT | ERR_FATAL;
4651 goto out;
4652 }
4653 mysqluser = args[cur_arg + 1];
4654 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004655
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004656 if (*(args[cur_arg+2])) {
4657 if (!strcmp(args[cur_arg+2], "post-41")) {
4658 packetlen = userlen + 7 + 27;
4659 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004660
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004661 free(curproxy->check_req);
4662 curproxy->check_req = (char *)calloc(1, reqlen);
4663 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004664
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004665 snprintf(curproxy->check_req, 4, "%c%c%c",
4666 ((unsigned char) packetlen & 0xff),
4667 ((unsigned char) (packetlen >> 8) & 0xff),
4668 ((unsigned char) (packetlen >> 16) & 0xff));
4669
4670 curproxy->check_req[3] = 1;
4671 curproxy->check_req[5] = 130;
4672 curproxy->check_req[11] = 1;
4673 curproxy->check_req[12] = 33;
4674 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4675 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4676 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4677 cur_arg += 3;
4678 } else {
4679 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4680 err_code |= ERR_ALERT | ERR_FATAL;
4681 goto out;
4682 }
4683 } else {
4684 packetlen = userlen + 7;
4685 reqlen = packetlen + 9;
4686
4687 free(curproxy->check_req);
4688 curproxy->check_req = (char *)calloc(1, reqlen);
4689 curproxy->check_len = reqlen;
4690
4691 snprintf(curproxy->check_req, 4, "%c%c%c",
4692 ((unsigned char) packetlen & 0xff),
4693 ((unsigned char) (packetlen >> 8) & 0xff),
4694 ((unsigned char) (packetlen >> 16) & 0xff));
4695
4696 curproxy->check_req[3] = 1;
4697 curproxy->check_req[5] = 128;
4698 curproxy->check_req[8] = 1;
4699 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4700 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4701 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4702 cur_arg += 2;
4703 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004704 } else {
4705 /* unknown suboption - catchall */
4706 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4707 file, linenum, args[0], args[1]);
4708 err_code |= ERR_ALERT | ERR_FATAL;
4709 goto out;
4710 }
4711 } /* end while loop */
4712 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004713 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004714 else if (!strcmp(args[1], "ldap-check")) {
4715 /* use LDAP request to check servers' health */
4716 free(curproxy->check_req);
4717 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004718 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004719 curproxy->options2 |= PR_O2_LDAP_CHK;
4720
4721 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
4722 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
4723 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004724 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4725 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004726 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004727 else if (!strcmp(args[1], "tcp-check")) {
4728 /* use raw TCPCHK send/expect to check servers' health */
4729 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4730 err_code |= ERR_WARN;
4731
4732 free(curproxy->check_req);
4733 curproxy->check_req = NULL;
4734 curproxy->options2 &= ~PR_O2_CHK_ANY;
4735 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004736 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4737 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02004738 }
Simon Horman98637e52014-06-20 12:30:16 +09004739 else if (!strcmp(args[1], "external-check")) {
4740 /* excute an external command to check servers' health */
4741 free(curproxy->check_req);
4742 curproxy->check_req = NULL;
4743 curproxy->options2 &= ~PR_O2_CHK_ANY;
4744 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004745 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4746 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09004747 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004748 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004749 int cur_arg;
4750
4751 /* insert x-forwarded-for field, but not for the IP address listed as an except.
4752 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004753 */
Ross Westaf72a1d2008-08-03 10:51:45 +02004754
Willy Tarreau87cf5142011-08-19 22:57:24 +02004755 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02004756
4757 free(curproxy->fwdfor_hdr_name);
4758 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
4759 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
4760
4761 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
4762 cur_arg = 2;
4763 while (*(args[cur_arg])) {
4764 if (!strcmp(args[cur_arg], "except")) {
4765 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004766 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02004767 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4768 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004769 err_code |= ERR_ALERT | ERR_FATAL;
4770 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004771 }
4772 /* flush useless bits */
4773 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02004774 cur_arg += 2;
4775 } else if (!strcmp(args[cur_arg], "header")) {
4776 /* suboption header - needs additional argument for it */
4777 if (*(args[cur_arg+1]) == 0) {
4778 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4779 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004780 err_code |= ERR_ALERT | ERR_FATAL;
4781 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02004782 }
4783 free(curproxy->fwdfor_hdr_name);
4784 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
4785 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
4786 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02004787 } else if (!strcmp(args[cur_arg], "if-none")) {
4788 curproxy->options &= ~PR_O_FF_ALWAYS;
4789 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004790 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02004791 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02004792 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02004793 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004794 err_code |= ERR_ALERT | ERR_FATAL;
4795 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004796 }
Ross Westaf72a1d2008-08-03 10:51:45 +02004797 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02004798 }
Maik Broemme2850cb42009-04-17 18:53:21 +02004799 else if (!strcmp(args[1], "originalto")) {
4800 int cur_arg;
4801
4802 /* insert x-original-to field, but not for the IP address listed as an except.
4803 * set default options (ie: bitfield, header name, etc)
4804 */
4805
4806 curproxy->options |= PR_O_ORGTO;
4807
4808 free(curproxy->orgto_hdr_name);
4809 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
4810 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
4811
Willy Tarreau87cf5142011-08-19 22:57:24 +02004812 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02004813 cur_arg = 2;
4814 while (*(args[cur_arg])) {
4815 if (!strcmp(args[cur_arg], "except")) {
4816 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01004817 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 +02004818 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
4819 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004820 err_code |= ERR_ALERT | ERR_FATAL;
4821 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004822 }
4823 /* flush useless bits */
4824 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
4825 cur_arg += 2;
4826 } else if (!strcmp(args[cur_arg], "header")) {
4827 /* suboption header - needs additional argument for it */
4828 if (*(args[cur_arg+1]) == 0) {
4829 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
4830 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02004831 err_code |= ERR_ALERT | ERR_FATAL;
4832 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004833 }
4834 free(curproxy->orgto_hdr_name);
4835 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
4836 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
4837 cur_arg += 2;
4838 } else {
4839 /* unknown suboption - catchall */
4840 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
4841 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004842 err_code |= ERR_ALERT | ERR_FATAL;
4843 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02004844 }
4845 } /* end while loop */
4846 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004847 else {
4848 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004849 err_code |= ERR_ALERT | ERR_FATAL;
4850 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004851 }
Willy Tarreau93893792009-07-23 13:19:11 +02004852 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004853 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004854 else if (!strcmp(args[0], "default_backend")) {
4855 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004856 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004857
4858 if (*(args[1]) == 0) {
4859 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004860 err_code |= ERR_ALERT | ERR_FATAL;
4861 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004862 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02004863 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004864 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02004865
4866 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4867 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01004868 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004869 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01004870 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004871 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01004872
Willy Tarreaua3c504c2014-04-28 22:37:32 +02004873 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
4874 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 +01004875 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004876 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004877 /* enable reconnections to dispatch */
4878 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02004879
4880 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
4881 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004882 }
Willy Tarreau48494c02007-11-30 10:41:39 +01004883 else if (!strcmp(args[0], "http-check")) {
4884 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004885 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01004886
4887 if (strcmp(args[1], "disable-on-404") == 0) {
4888 /* enable a graceful server shutdown on an HTTP 404 response */
4889 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02004890 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4891 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01004892 }
Willy Tarreauef781042010-01-27 11:53:01 +01004893 else if (strcmp(args[1], "send-state") == 0) {
4894 /* enable emission of the apparent state of a server in HTTP checks */
4895 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02004896 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4897 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01004898 }
Willy Tarreaubd741542010-03-16 18:46:54 +01004899 else if (strcmp(args[1], "expect") == 0) {
4900 const char *ptr_arg;
4901 int cur_arg;
4902
4903 if (curproxy->options2 & PR_O2_EXP_TYPE) {
4904 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
4905 err_code |= ERR_ALERT | ERR_FATAL;
4906 goto out;
4907 }
4908
4909 cur_arg = 2;
4910 /* consider exclamation marks, sole or at the beginning of a word */
4911 while (*(ptr_arg = args[cur_arg])) {
4912 while (*ptr_arg == '!') {
4913 curproxy->options2 ^= PR_O2_EXP_INV;
4914 ptr_arg++;
4915 }
4916 if (*ptr_arg)
4917 break;
4918 cur_arg++;
4919 }
4920 /* now ptr_arg points to the beginning of a word past any possible
4921 * exclamation mark, and cur_arg is the argument which holds this word.
4922 */
4923 if (strcmp(ptr_arg, "status") == 0) {
4924 if (!*(args[cur_arg + 1])) {
4925 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4926 file, linenum, args[0], args[1], ptr_arg);
4927 err_code |= ERR_ALERT | ERR_FATAL;
4928 goto out;
4929 }
4930 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004931 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004932 curproxy->expect_str = strdup(args[cur_arg + 1]);
4933 }
4934 else if (strcmp(ptr_arg, "string") == 0) {
4935 if (!*(args[cur_arg + 1])) {
4936 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
4937 file, linenum, args[0], args[1], ptr_arg);
4938 err_code |= ERR_ALERT | ERR_FATAL;
4939 goto out;
4940 }
4941 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004942 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01004943 curproxy->expect_str = strdup(args[cur_arg + 1]);
4944 }
4945 else if (strcmp(ptr_arg, "rstatus") == 0) {
4946 if (!*(args[cur_arg + 1])) {
4947 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4948 file, linenum, args[0], args[1], ptr_arg);
4949 err_code |= ERR_ALERT | ERR_FATAL;
4950 goto out;
4951 }
4952 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004953 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004954 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004955 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004956 free(curproxy->expect_regex);
4957 curproxy->expect_regex = NULL;
4958 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004959 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004960 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4961 error = NULL;
4962 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4963 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4964 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4965 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004966 err_code |= ERR_ALERT | ERR_FATAL;
4967 goto out;
4968 }
4969 }
4970 else if (strcmp(ptr_arg, "rstring") == 0) {
4971 if (!*(args[cur_arg + 1])) {
4972 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
4973 file, linenum, args[0], args[1], ptr_arg);
4974 err_code |= ERR_ALERT | ERR_FATAL;
4975 goto out;
4976 }
4977 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004978 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004979 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004980 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02004981 free(curproxy->expect_regex);
4982 curproxy->expect_regex = NULL;
4983 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02004984 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02004985 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
4986 error = NULL;
4987 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
4988 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
4989 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
4990 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01004991 err_code |= ERR_ALERT | ERR_FATAL;
4992 goto out;
4993 }
4994 }
4995 else {
4996 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
4997 file, linenum, args[0], args[1], ptr_arg);
4998 err_code |= ERR_ALERT | ERR_FATAL;
4999 goto out;
5000 }
5001 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005002 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005003 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 +02005004 err_code |= ERR_ALERT | ERR_FATAL;
5005 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005006 }
5007 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005008 else if (!strcmp(args[0], "tcp-check")) {
5009 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5010 err_code |= ERR_WARN;
5011
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005012 if (strcmp(args[1], "comment") == 0) {
5013 int cur_arg;
5014 struct tcpcheck_rule *tcpcheck;
5015
5016 cur_arg = 1;
5017 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5018 tcpcheck->action = TCPCHK_ACT_COMMENT;
5019
5020 if (!*args[cur_arg + 1]) {
5021 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5022 file, linenum, args[cur_arg]);
5023 err_code |= ERR_ALERT | ERR_FATAL;
5024 goto out;
5025 }
5026
5027 tcpcheck->comment = strdup(args[cur_arg + 1]);
5028
5029 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005030 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5031 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005032 }
5033 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005034 const char *ptr_arg;
5035 int cur_arg;
5036 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005037
5038 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005039 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5040 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5041 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5042 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5043 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005044
Willy Tarreau5581c272015-05-13 12:24:53 +02005045 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5046 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5047 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5048 file, linenum);
5049 err_code |= ERR_ALERT | ERR_FATAL;
5050 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005051 }
5052
5053 cur_arg = 2;
5054 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5055 tcpcheck->action = TCPCHK_ACT_CONNECT;
5056
5057 /* parsing each parameters to fill up the rule */
5058 while (*(ptr_arg = args[cur_arg])) {
5059 /* tcp port */
5060 if (strcmp(args[cur_arg], "port") == 0) {
5061 if ( (atol(args[cur_arg + 1]) > 65535) ||
5062 (atol(args[cur_arg + 1]) < 1) ){
5063 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5064 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5065 err_code |= ERR_ALERT | ERR_FATAL;
5066 goto out;
5067 }
5068 tcpcheck->port = atol(args[cur_arg + 1]);
5069 cur_arg += 2;
5070 }
5071 /* send proxy protocol */
5072 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5073 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5074 cur_arg++;
5075 }
5076#ifdef USE_OPENSSL
5077 else if (strcmp(args[cur_arg], "ssl") == 0) {
5078 curproxy->options |= PR_O_TCPCHK_SSL;
5079 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5080 cur_arg++;
5081 }
5082#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005083 /* comment for this tcpcheck line */
5084 else if (strcmp(args[cur_arg], "comment") == 0) {
5085 if (!*args[cur_arg + 1]) {
5086 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5087 file, linenum, args[cur_arg]);
5088 err_code |= ERR_ALERT | ERR_FATAL;
5089 goto out;
5090 }
5091 tcpcheck->comment = strdup(args[cur_arg + 1]);
5092 cur_arg += 2;
5093 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005094 else {
5095#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005096 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 +01005097#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005098 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 +01005099#endif /* USE_OPENSSL */
5100 file, linenum, args[0], args[1], args[cur_arg]);
5101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
5103 }
5104
5105 }
5106
5107 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5108 }
5109 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005110 if (! *(args[2]) ) {
5111 /* SEND string expected */
5112 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5113 file, linenum, args[0], args[1], args[2]);
5114 err_code |= ERR_ALERT | ERR_FATAL;
5115 goto out;
5116 } else {
5117 struct tcpcheck_rule *tcpcheck;
5118
5119 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5120
5121 tcpcheck->action = TCPCHK_ACT_SEND;
5122 tcpcheck->string_len = strlen(args[2]);
5123 tcpcheck->string = strdup(args[2]);
5124 tcpcheck->expect_regex = NULL;
5125
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005126 /* comment for this tcpcheck line */
5127 if (strcmp(args[3], "comment") == 0) {
5128 if (!*args[4]) {
5129 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5130 file, linenum, args[3]);
5131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
5133 }
5134 tcpcheck->comment = strdup(args[4]);
5135 }
5136
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005137 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5138 }
5139 }
5140 else if (strcmp(args[1], "send-binary") == 0) {
5141 if (! *(args[2]) ) {
5142 /* SEND binary string expected */
5143 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5144 file, linenum, args[0], args[1], args[2]);
5145 err_code |= ERR_ALERT | ERR_FATAL;
5146 goto out;
5147 } else {
5148 struct tcpcheck_rule *tcpcheck;
5149 char *err = NULL;
5150
5151 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5152
5153 tcpcheck->action = TCPCHK_ACT_SEND;
5154 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5155 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5156 file, linenum, args[0], args[1], args[2], err);
5157 err_code |= ERR_ALERT | ERR_FATAL;
5158 goto out;
5159 }
5160 tcpcheck->expect_regex = NULL;
5161
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005162 /* comment for this tcpcheck line */
5163 if (strcmp(args[3], "comment") == 0) {
5164 if (!*args[4]) {
5165 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5166 file, linenum, args[3]);
5167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
5169 }
5170 tcpcheck->comment = strdup(args[4]);
5171 }
5172
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005173 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5174 }
5175 }
5176 else if (strcmp(args[1], "expect") == 0) {
5177 const char *ptr_arg;
5178 int cur_arg;
5179 int inverse = 0;
5180
5181 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5182 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5183 err_code |= ERR_ALERT | ERR_FATAL;
5184 goto out;
5185 }
5186
5187 cur_arg = 2;
5188 /* consider exclamation marks, sole or at the beginning of a word */
5189 while (*(ptr_arg = args[cur_arg])) {
5190 while (*ptr_arg == '!') {
5191 inverse = !inverse;
5192 ptr_arg++;
5193 }
5194 if (*ptr_arg)
5195 break;
5196 cur_arg++;
5197 }
5198 /* now ptr_arg points to the beginning of a word past any possible
5199 * exclamation mark, and cur_arg is the argument which holds this word.
5200 */
5201 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005202 struct tcpcheck_rule *tcpcheck;
5203 char *err = NULL;
5204
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005205 if (!*(args[cur_arg + 1])) {
5206 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5207 file, linenum, args[0], args[1], ptr_arg);
5208 err_code |= ERR_ALERT | ERR_FATAL;
5209 goto out;
5210 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005211
5212 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5213
5214 tcpcheck->action = TCPCHK_ACT_EXPECT;
5215 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5216 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5217 file, linenum, args[0], args[1], args[2], err);
5218 err_code |= ERR_ALERT | ERR_FATAL;
5219 goto out;
5220 }
5221 tcpcheck->expect_regex = NULL;
5222 tcpcheck->inverse = inverse;
5223
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005224 /* tcpcheck comment */
5225 cur_arg += 2;
5226 if (strcmp(args[cur_arg], "comment") == 0) {
5227 if (!*args[cur_arg + 1]) {
5228 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5229 file, linenum, args[cur_arg + 1]);
5230 err_code |= ERR_ALERT | ERR_FATAL;
5231 goto out;
5232 }
5233 tcpcheck->comment = strdup(args[cur_arg + 1]);
5234 }
5235
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005236 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5237 }
5238 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005239 struct tcpcheck_rule *tcpcheck;
5240
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005241 if (!*(args[cur_arg + 1])) {
5242 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5243 file, linenum, args[0], args[1], ptr_arg);
5244 err_code |= ERR_ALERT | ERR_FATAL;
5245 goto out;
5246 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005247
5248 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5249
5250 tcpcheck->action = TCPCHK_ACT_EXPECT;
5251 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5252 tcpcheck->string = strdup(args[cur_arg + 1]);
5253 tcpcheck->expect_regex = NULL;
5254 tcpcheck->inverse = inverse;
5255
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005256 /* tcpcheck comment */
5257 cur_arg += 2;
5258 if (strcmp(args[cur_arg], "comment") == 0) {
5259 if (!*args[cur_arg + 1]) {
5260 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5261 file, linenum, args[cur_arg + 1]);
5262 err_code |= ERR_ALERT | ERR_FATAL;
5263 goto out;
5264 }
5265 tcpcheck->comment = strdup(args[cur_arg + 1]);
5266 }
5267
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005268 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5269 }
5270 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005271 struct tcpcheck_rule *tcpcheck;
5272
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005273 if (!*(args[cur_arg + 1])) {
5274 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5275 file, linenum, args[0], args[1], ptr_arg);
5276 err_code |= ERR_ALERT | ERR_FATAL;
5277 goto out;
5278 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005279
5280 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5281
5282 tcpcheck->action = TCPCHK_ACT_EXPECT;
5283 tcpcheck->string_len = 0;
5284 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005285 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5286 error = NULL;
5287 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5288 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5289 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5290 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005291 err_code |= ERR_ALERT | ERR_FATAL;
5292 goto out;
5293 }
5294 tcpcheck->inverse = inverse;
5295
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005296 /* tcpcheck comment */
5297 cur_arg += 2;
5298 if (strcmp(args[cur_arg], "comment") == 0) {
5299 if (!*args[cur_arg + 1]) {
5300 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5301 file, linenum, args[cur_arg + 1]);
5302 err_code |= ERR_ALERT | ERR_FATAL;
5303 goto out;
5304 }
5305 tcpcheck->comment = strdup(args[cur_arg + 1]);
5306 }
5307
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005308 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5309 }
5310 else {
5311 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5312 file, linenum, args[0], args[1], ptr_arg);
5313 err_code |= ERR_ALERT | ERR_FATAL;
5314 goto out;
5315 }
5316 }
5317 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005318 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005319 err_code |= ERR_ALERT | ERR_FATAL;
5320 goto out;
5321 }
5322 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005323 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005324 if (curproxy == &defproxy) {
5325 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005326 err_code |= ERR_ALERT | ERR_FATAL;
5327 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005328 }
5329
Willy Tarreaub80c2302007-11-30 20:51:32 +01005330 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005331 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005332
5333 if (strcmp(args[1], "fail") == 0) {
5334 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005335 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005336 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5337 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005338 err_code |= ERR_ALERT | ERR_FATAL;
5339 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005340 }
5341
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005342 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5343 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5344 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005345 err_code |= ERR_ALERT | ERR_FATAL;
5346 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005347 }
5348 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5349 }
5350 else {
5351 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005352 err_code |= ERR_ALERT | ERR_FATAL;
5353 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005354 }
5355 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005356#ifdef TPROXY
5357 else if (!strcmp(args[0], "transparent")) {
5358 /* enable transparent proxy connections */
5359 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005360 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5361 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005362 }
5363#endif
5364 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005365 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005366 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005367
Willy Tarreaubaaee002006-06-26 02:48:02 +02005368 if (*(args[1]) == 0) {
5369 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005370 err_code |= ERR_ALERT | ERR_FATAL;
5371 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005372 }
5373 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005374 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005376 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005377 else if (!strcmp(args[0], "backlog")) { /* backlog */
5378 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005379 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005380
5381 if (*(args[1]) == 0) {
5382 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005383 err_code |= ERR_ALERT | ERR_FATAL;
5384 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005385 }
5386 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005387 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5388 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005389 }
Willy Tarreau86034312006-12-29 00:10:33 +01005390 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005391 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005392 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005393
Willy Tarreau86034312006-12-29 00:10:33 +01005394 if (*(args[1]) == 0) {
5395 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005398 }
5399 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005400 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5401 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005402 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005403 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5404 if (*(args[1]) == 0) {
5405 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005406 err_code |= ERR_ALERT | ERR_FATAL;
5407 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005408 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005409 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5410 if (err) {
5411 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5412 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005413 err_code |= ERR_ALERT | ERR_FATAL;
5414 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005415 }
5416 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005417 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005419 }
5420 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005421 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005422 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005423 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005424
Willy Tarreaubaaee002006-06-26 02:48:02 +02005425 if (curproxy == &defproxy) {
5426 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005427 err_code |= ERR_ALERT | ERR_FATAL;
5428 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005429 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005430 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005431 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005432
Willy Tarreau902636f2013-03-10 19:44:48 +01005433 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005434 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005435 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005436 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005437 goto out;
5438 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005439
5440 proto = protocol_by_family(sk->ss_family);
5441 if (!proto || !proto->connect) {
5442 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5443 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005444 err_code |= ERR_ALERT | ERR_FATAL;
5445 goto out;
5446 }
5447
5448 if (port1 != port2) {
5449 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5450 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005451 err_code |= ERR_ALERT | ERR_FATAL;
5452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005453 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005454
5455 if (!port1) {
5456 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5457 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005458 err_code |= ERR_ALERT | ERR_FATAL;
5459 goto out;
5460 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005461
William Lallemanddf1425a2015-04-28 20:17:49 +02005462 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5463 goto out;
5464
Willy Tarreaud5191e72010-02-09 20:50:45 +01005465 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005466 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005467 }
5468 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005469 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005470 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005471
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005472 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5473 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005474 err_code |= ERR_ALERT | ERR_FATAL;
5475 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005476 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005477 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005478 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005479 /**
5480 * The syntax for hash-type config element is
5481 * hash-type {map-based|consistent} [[<algo>] avalanche]
5482 *
5483 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5484 */
5485 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005486
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005487 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5488 err_code |= ERR_WARN;
5489
5490 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005491 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5492 }
5493 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005494 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5495 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005496 else if (strcmp(args[1], "avalanche") == 0) {
5497 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]);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005500 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005501 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005502 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005503 err_code |= ERR_ALERT | ERR_FATAL;
5504 goto out;
5505 }
Bhaskar98634f02013-10-29 23:30:51 -04005506
5507 /* set the hash function to use */
5508 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005509 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005510 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005511
5512 /* if consistent with no argument, then avalanche modifier is also applied */
5513 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5514 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005515 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005516 /* set the hash function */
5517 if (!strcmp(args[2], "sdbm")) {
5518 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5519 }
5520 else if (!strcmp(args[2], "djb2")) {
5521 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005522 }
5523 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005524 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005525 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005526 else if (!strcmp(args[2], "crc32")) {
5527 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5528 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005529 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005530 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 -05005531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 }
5534
5535 /* set the hash modifier */
5536 if (!strcmp(args[3], "avalanche")) {
5537 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5538 }
5539 else if (*args[3]) {
5540 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005544 }
William Lallemanda73203e2012-03-12 12:48:57 +01005545 }
William Lallemanda73203e2012-03-12 12:48:57 +01005546 else if (strcmp(args[0], "unique-id-format") == 0) {
5547 if (!*(args[1])) {
5548 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
5551 }
William Lallemand3203ff42012-11-11 17:30:56 +01005552 if (*(args[2])) {
5553 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5554 err_code |= ERR_ALERT | ERR_FATAL;
5555 goto out;
5556 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005557 free(curproxy->conf.uniqueid_format_string);
5558 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005559
Willy Tarreau62a61232013-04-12 18:13:46 +02005560 free(curproxy->conf.uif_file);
5561 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5562 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005563 }
William Lallemanda73203e2012-03-12 12:48:57 +01005564
5565 else if (strcmp(args[0], "unique-id-header") == 0) {
5566 if (!*(args[1])) {
5567 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5568 err_code |= ERR_ALERT | ERR_FATAL;
5569 goto out;
5570 }
5571 free(curproxy->header_unique_id);
5572 curproxy->header_unique_id = strdup(args[1]);
5573 }
5574
William Lallemand723b73a2012-02-08 16:37:49 +01005575 else if (strcmp(args[0], "log-format") == 0) {
5576 if (!*(args[1])) {
5577 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5578 err_code |= ERR_ALERT | ERR_FATAL;
5579 goto out;
5580 }
William Lallemand3203ff42012-11-11 17:30:56 +01005581 if (*(args[2])) {
5582 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5583 err_code |= ERR_ALERT | ERR_FATAL;
5584 goto out;
5585 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005586
Willy Tarreau62a61232013-04-12 18:13:46 +02005587 if (curproxy->conf.logformat_string != default_http_log_format &&
5588 curproxy->conf.logformat_string != default_tcp_log_format &&
5589 curproxy->conf.logformat_string != clf_http_log_format)
5590 free(curproxy->conf.logformat_string);
5591 curproxy->conf.logformat_string = strdup(args[1]);
5592
5593 free(curproxy->conf.lfs_file);
5594 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5595 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005596
5597 /* get a chance to improve log-format error reporting by
5598 * reporting the correct line-number when possible.
5599 */
5600 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5601 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5602 file, linenum, curproxy->id);
5603 err_code |= ERR_WARN;
5604 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005605 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005606 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5607 if (*(args[1]) == 0) {
5608 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5609 err_code |= ERR_ALERT | ERR_FATAL;
5610 goto out;
5611 }
5612 free(curproxy->log_tag);
5613 curproxy->log_tag = strdup(args[1]);
5614 }
William Lallemand0f99e342011-10-12 17:50:54 +02005615 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5616 /* delete previous herited or defined syslog servers */
5617 struct logsrv *back;
5618
5619 if (*(args[1]) != 0) {
5620 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5621 err_code |= ERR_ALERT | ERR_FATAL;
5622 goto out;
5623 }
5624
William Lallemand723b73a2012-02-08 16:37:49 +01005625 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5626 LIST_DEL(&tmplogsrv->list);
5627 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005628 }
5629 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005630 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005631 struct logsrv *logsrv;
5632
Willy Tarreaubaaee002006-06-26 02:48:02 +02005633 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005634 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005635 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005636 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005637 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005638 LIST_INIT(&node->list);
5639 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5640 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005641 }
5642 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005643 struct sockaddr_storage *sk;
5644 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005645 int arg = 0;
5646 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005647
5648 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005649
Willy Tarreau18324f52014-06-27 18:10:07 +02005650 /* just after the address, a length may be specified */
5651 if (strcmp(args[arg+2], "len") == 0) {
5652 len = atoi(args[arg+3]);
5653 if (len < 80 || len > 65535) {
5654 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
5655 file, linenum, args[arg+3]);
5656 err_code |= ERR_ALERT | ERR_FATAL;
5657 goto out;
5658 }
5659 logsrv->maxlen = len;
5660
5661 /* skip these two args */
5662 arg += 2;
5663 }
5664 else
5665 logsrv->maxlen = MAX_SYSLOG_LEN;
5666
5667 if (logsrv->maxlen > global.max_syslog_len) {
5668 global.max_syslog_len = logsrv->maxlen;
5669 logline = realloc(logline, global.max_syslog_len + 1);
5670 }
5671
William Lallemanddf1425a2015-04-28 20:17:49 +02005672 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
5673 goto out;
5674
Willy Tarreau18324f52014-06-27 18:10:07 +02005675 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005676 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005677 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02005678 err_code |= ERR_ALERT | ERR_FATAL;
5679 goto out;
5680
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682
William Lallemand0f99e342011-10-12 17:50:54 +02005683 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02005684 if (*(args[arg+3])) {
5685 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005686 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005687 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02005688 err_code |= ERR_ALERT | ERR_FATAL;
5689 goto out;
5690
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
5692 }
5693
William Lallemand0f99e342011-10-12 17:50:54 +02005694 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02005695 if (*(args[arg+4])) {
5696 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01005697 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02005698 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02005699 err_code |= ERR_ALERT | ERR_FATAL;
5700 goto out;
5701
Willy Tarreauf7edefa2009-05-10 17:20:05 +02005702 }
5703 }
5704
Willy Tarreau902636f2013-03-10 19:44:48 +01005705 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005706 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005707 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005708 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005709 goto out;
5710 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005711
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005712 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005713
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005714 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005715 if (port1 != port2) {
5716 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5717 file, linenum, args[0], args[1]);
5718 err_code |= ERR_ALERT | ERR_FATAL;
5719 goto out;
5720 }
5721
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005722 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02005723 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005724 }
William Lallemand0f99e342011-10-12 17:50:54 +02005725
5726 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
5728 else {
5729 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
5730 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02005731 err_code |= ERR_ALERT | ERR_FATAL;
5732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005733 }
5734 }
5735 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005736 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005737 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01005738 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005739 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005740
Willy Tarreau977b8e42006-12-29 14:19:17 +01005741 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005742 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005743
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005745 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
5746 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02005747 err_code |= ERR_ALERT | ERR_FATAL;
5748 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005749 }
Willy Tarreau368480c2009-03-01 08:27:21 +01005750
5751 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01005752 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5753 free(curproxy->conn_src.iface_name);
5754 curproxy->conn_src.iface_name = NULL;
5755 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01005756
Willy Tarreau902636f2013-03-10 19:44:48 +01005757 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005758 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005759 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005760 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005761 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005762 goto out;
5763 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005764
5765 proto = protocol_by_family(sk->ss_family);
5766 if (!proto || !proto->connect) {
5767 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005768 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005769 err_code |= ERR_ALERT | ERR_FATAL;
5770 goto out;
5771 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005772
5773 if (port1 != port2) {
5774 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5775 file, linenum, args[0], args[1]);
5776 err_code |= ERR_ALERT | ERR_FATAL;
5777 goto out;
5778 }
5779
Willy Tarreauef9a3602012-12-08 22:29:20 +01005780 curproxy->conn_src.source_addr = *sk;
5781 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005782
5783 cur_arg = 2;
5784 while (*(args[cur_arg])) {
5785 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Pieter Baauwd551fb52013-05-08 22:49:23 +02005786#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
5787#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreau9cf8d3f2014-05-09 22:56:10 +02005788 if (!is_inet_addr(&curproxy->conn_src.source_addr)) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005789 Alert("parsing [%s:%d] : '%s' requires an explicit 'source' address.\n",
5790 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005791 err_code |= ERR_ALERT | ERR_FATAL;
5792 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005793 }
5794#endif
5795 if (!*args[cur_arg + 1]) {
5796 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
5797 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005798 err_code |= ERR_ALERT | ERR_FATAL;
5799 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005800 }
5801
5802 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005803 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5804 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005805 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01005806 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5807 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02005808 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
5809 char *name, *end;
5810
5811 name = args[cur_arg+1] + 7;
5812 while (isspace(*name))
5813 name++;
5814
5815 end = name;
5816 while (*end && !isspace(*end) && *end != ',' && *end != ')')
5817 end++;
5818
Willy Tarreauef9a3602012-12-08 22:29:20 +01005819 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
5820 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
5821 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
5822 curproxy->conn_src.bind_hdr_len = end - name;
5823 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
5824 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
5825 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02005826
5827 /* now look for an occurrence number */
5828 while (isspace(*end))
5829 end++;
5830 if (*end == ',') {
5831 end++;
5832 name = end;
5833 if (*end == '-')
5834 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01005835 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02005836 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01005837 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02005838 }
5839
Willy Tarreauef9a3602012-12-08 22:29:20 +01005840 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02005841 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
5842 " occurrences values smaller than %d.\n",
5843 file, linenum, MAX_HDR_HISTORY);
5844 err_code |= ERR_ALERT | ERR_FATAL;
5845 goto out;
5846 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005847 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01005848 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005849
Willy Tarreau902636f2013-03-10 19:44:48 +01005850 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005851 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005852 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01005853 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005854 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005855 goto out;
5856 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005857
5858 proto = protocol_by_family(sk->ss_family);
5859 if (!proto || !proto->connect) {
5860 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5861 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005862 err_code |= ERR_ALERT | ERR_FATAL;
5863 goto out;
5864 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01005865
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005866 if (port1 != port2) {
5867 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
5868 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005869 err_code |= ERR_ALERT | ERR_FATAL;
5870 goto out;
5871 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005872 curproxy->conn_src.tproxy_addr = *sk;
5873 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005874 }
5875 global.last_checks |= LSTCHK_NETADM;
Pieter Baauwd551fb52013-05-08 22:49:23 +02005876#if !defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005877 global.last_checks |= LSTCHK_CTTPROXY;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005878#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005879#else /* no TPROXY support */
5880 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01005881 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005884#endif
5885 cur_arg += 2;
5886 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01005887 }
5888
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005889 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
5890#ifdef SO_BINDTODEVICE
5891 if (!*args[cur_arg + 1]) {
5892 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
5893 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005894 err_code |= ERR_ALERT | ERR_FATAL;
5895 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005896 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01005897 free(curproxy->conn_src.iface_name);
5898 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
5899 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005900 global.last_checks |= LSTCHK_NETADM;
5901#else
5902 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
5903 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01005906#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01005907 cur_arg += 2;
5908 continue;
5909 }
5910 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02005911 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02005912 err_code |= ERR_ALERT | ERR_FATAL;
5913 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005914 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005915 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005916 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
5917 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
5918 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02005919 err_code |= ERR_ALERT | ERR_FATAL;
5920 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01005921 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005922 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005923 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5925 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005926 err_code |= ERR_ALERT | ERR_FATAL;
5927 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005928 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005929
5930 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005931 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005932 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005933 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005934 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005935 }
5936 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005937 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005938 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005939 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005940 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005941 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005942 }
5943 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005944 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005945 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005946 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005947 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005948 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005949 }
5950 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005951 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005952 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005953 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005954 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005955 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005956 }
5957 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005958 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005959 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005960 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005961 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005962 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005963 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02005964 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005965 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005966 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01005967 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005968 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005969 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02005970 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005971 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005972 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02005973 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
5974 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005975 err_code |= ERR_ALERT | ERR_FATAL;
5976 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005977 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01005978
5979 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005980 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005981 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005982 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005983 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005984 }
5985 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005986 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005987 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005988 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005989 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005990 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005991 }
5992 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01005993 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02005994 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01005995 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01005996 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02005997 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005998 }
5999 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006000 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006001 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006002 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006003 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006004 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006005 }
6006 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006007 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006008 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006009 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006010 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006012 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006013 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006014 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006015 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006016 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006017 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006018 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006019 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006020 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006021 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006022
Willy Tarreaubaaee002006-06-26 02:48:02 +02006023 if (curproxy == &defproxy) {
6024 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006025 err_code |= ERR_ALERT | ERR_FATAL;
6026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006027 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006028 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006029 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006030
Willy Tarreaubaaee002006-06-26 02:48:02 +02006031 if (*(args[1]) == 0) {
6032 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006033 err_code |= ERR_ALERT | ERR_FATAL;
6034 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006035 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006036
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006037 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006038 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6039 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6040 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006041 err_code |= ERR_ALERT | ERR_FATAL;
6042 goto out;
6043 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006044 err_code |= warnif_cond_conflicts(cond,
6045 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6046 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006047 }
6048 else if (*args[2]) {
6049 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6050 file, linenum, args[0], args[2]);
6051 err_code |= ERR_ALERT | ERR_FATAL;
6052 goto out;
6053 }
6054
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006055 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006056 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006057 wl->s = strdup(args[1]);
6058 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006059 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006060 }
6061 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006062 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006063 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6064 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006065 err_code |= ERR_ALERT | ERR_FATAL;
6066 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006067 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006068
Willy Tarreauade5ec42010-01-28 19:33:49 +01006069 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006070 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006071 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006072 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006073 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006074 }
6075 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006076 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006077 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006078 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006079 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006080 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006081 }
6082 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006083 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006084 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006085 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006086 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006088 }
6089 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006090 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6092 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006093 err_code |= ERR_ALERT | ERR_FATAL;
6094 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006095 }
6096
Willy Tarreauade5ec42010-01-28 19:33:49 +01006097 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006098 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006099 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006100 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006101 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102 }
6103 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006104 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006105 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006106 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006107 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006108 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006109 }
6110 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006111 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006112 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006113 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006114 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006115 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006116 }
6117 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006118 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006119
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120 if (curproxy == &defproxy) {
6121 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006122 err_code |= ERR_ALERT | ERR_FATAL;
6123 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006124 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006125 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006126 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006127
Willy Tarreaubaaee002006-06-26 02:48:02 +02006128 if (*(args[1]) == 0) {
6129 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006130 err_code |= ERR_ALERT | ERR_FATAL;
6131 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006132 }
6133
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006134 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006135 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6136 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6137 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006138 err_code |= ERR_ALERT | ERR_FATAL;
6139 goto out;
6140 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006141 err_code |= warnif_cond_conflicts(cond,
6142 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6143 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006144 }
6145 else if (*args[2]) {
6146 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6147 file, linenum, args[0], args[2]);
6148 err_code |= ERR_ALERT | ERR_FATAL;
6149 goto out;
6150 }
6151
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006152 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006153 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006154 wl->s = strdup(args[1]);
6155 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
6157 else if (!strcmp(args[0], "errorloc") ||
6158 !strcmp(args[0], "errorloc302") ||
6159 !strcmp(args[0], "errorloc303")) { /* error location */
6160 int errnum, errlen;
6161 char *err;
6162
Willy Tarreau977b8e42006-12-29 14:19:17 +01006163 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006164 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006165
Willy Tarreaubaaee002006-06-26 02:48:02 +02006166 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006167 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006168 err_code |= ERR_ALERT | ERR_FATAL;
6169 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006170 }
6171
6172 errnum = atol(args[1]);
6173 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006174 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6175 err = malloc(errlen);
6176 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006177 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006178 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6179 err = malloc(errlen);
6180 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006181 }
6182
Willy Tarreau0f772532006-12-23 20:51:41 +01006183 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6184 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006185 chunk_destroy(&curproxy->errmsg[rc]);
6186 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006187 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006188 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006189 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006190
6191 if (rc >= HTTP_ERR_SIZE) {
6192 Warning("parsing [%s:%d] : status code %d not handled, error relocation will be ignored.\n",
6193 file, linenum, errnum);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006194 free(err);
6195 }
6196 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006197 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6198 int errnum, errlen, fd;
6199 char *err;
6200 struct stat stat;
6201
6202 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006203 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006204
6205 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006206 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006207 err_code |= ERR_ALERT | ERR_FATAL;
6208 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006209 }
6210
6211 fd = open(args[2], O_RDONLY);
6212 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6213 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6214 file, linenum, args[2], args[1]);
6215 if (fd >= 0)
6216 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006217 err_code |= ERR_ALERT | ERR_FATAL;
6218 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006219 }
6220
Willy Tarreau27a674e2009-08-17 07:23:33 +02006221 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006222 errlen = stat.st_size;
6223 } else {
6224 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006225 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006226 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006227 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006228 }
6229
6230 err = malloc(errlen); /* malloc() must succeed during parsing */
6231 errnum = read(fd, err, errlen);
6232 if (errnum != errlen) {
6233 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6234 file, linenum, args[2], args[1]);
6235 close(fd);
6236 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006237 err_code |= ERR_ALERT | ERR_FATAL;
6238 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006239 }
6240 close(fd);
6241
6242 errnum = atol(args[1]);
6243 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6244 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006245 chunk_destroy(&curproxy->errmsg[rc]);
6246 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006247 break;
6248 }
6249 }
6250
6251 if (rc >= HTTP_ERR_SIZE) {
6252 Warning("parsing [%s:%d] : status code %d not handled, error customization will be ignored.\n",
6253 file, linenum, errnum);
Willy Tarreau93893792009-07-23 13:19:11 +02006254 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006255 free(err);
6256 }
6257 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006258 else if (!strcmp(args[0], "compression")) {
6259 struct comp *comp;
6260 if (curproxy->comp == NULL) {
6261 comp = calloc(1, sizeof(struct comp));
6262 curproxy->comp = comp;
6263 } else {
6264 comp = curproxy->comp;
6265 }
6266
6267 if (!strcmp(args[1], "algo")) {
6268 int cur_arg;
William Lallemand8b52bb32012-11-16 18:06:41 +01006269 struct comp_ctx *ctx;
William Lallemand552df672012-11-07 13:21:47 +01006270
William Lallemand82fe75c2012-10-23 10:25:10 +02006271 cur_arg = 2;
6272 if (!*args[cur_arg]) {
6273 Alert("parsing [%s:%d] : '%s' expects <algorithm>\n",
6274 file, linenum, args[0]);
6275 err_code |= ERR_ALERT | ERR_FATAL;
6276 goto out;
6277 }
6278 while (*(args[cur_arg])) {
6279 if (comp_append_algo(comp, args[cur_arg]) < 0) {
6280 Alert("parsing [%s:%d] : '%s' : '%s' is not a supported algorithm.\n",
6281 file, linenum, args[0], args[cur_arg]);
6282 err_code |= ERR_ALERT | ERR_FATAL;
6283 goto out;
6284 }
William Lallemand552df672012-11-07 13:21:47 +01006285 if (curproxy->comp->algos->init(&ctx, 9) == 0) {
6286 curproxy->comp->algos->end(&ctx);
6287 } else {
6288 Alert("parsing [%s:%d] : '%s' : Can't init '%s' algorithm.\n",
6289 file, linenum, args[0], args[cur_arg]);
6290 err_code |= ERR_ALERT | ERR_FATAL;
6291 goto out;
6292 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006293 cur_arg ++;
6294 continue;
6295 }
6296 }
Willy Tarreau70737d12012-10-27 00:34:28 +02006297 else if (!strcmp(args[1], "offload")) {
6298 comp->offload = 1;
6299 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006300 else if (!strcmp(args[1], "type")) {
6301 int cur_arg;
6302 cur_arg = 2;
6303 if (!*args[cur_arg]) {
6304 Alert("parsing [%s:%d] : '%s' expects <type>\n",
6305 file, linenum, args[0]);
6306 err_code |= ERR_ALERT | ERR_FATAL;
6307 goto out;
6308 }
6309 while (*(args[cur_arg])) {
6310 comp_append_type(comp, args[cur_arg]);
6311 cur_arg ++;
6312 continue;
6313 }
6314 }
6315 else {
Willy Tarreau70737d12012-10-27 00:34:28 +02006316 Alert("parsing [%s:%d] : '%s' expects 'algo', 'type' or 'offload'\n",
William Lallemand82fe75c2012-10-23 10:25:10 +02006317 file, linenum, args[0]);
6318 err_code |= ERR_ALERT | ERR_FATAL;
6319 goto out;
6320 }
6321 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006322 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006323 struct cfg_kw_list *kwl;
6324 int index;
6325
6326 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6327 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6328 if (kwl->kw[index].section != CFG_LISTEN)
6329 continue;
6330 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6331 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006332 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006333 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006334 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006335 err_code |= ERR_ALERT | ERR_FATAL;
6336 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006337 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006338 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006339 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006340 err_code |= ERR_WARN;
6341 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006342 }
Willy Tarreau93893792009-07-23 13:19:11 +02006343 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006344 }
6345 }
6346 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006347
Willy Tarreau6daf3432008-01-22 16:44:08 +01006348 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
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 }
Willy Tarreau93893792009-07-23 13:19:11 +02006352 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006353 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006354 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006355}
6356
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006357int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006358cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6359{
6360#ifdef CONFIG_HAP_NS
6361 const char *err;
6362 const char *item = args[0];
6363
6364 if (!strcmp(item, "namespace_list")) {
6365 return 0;
6366 }
6367 else if (!strcmp(item, "namespace")) {
6368 size_t idx = 1;
6369 const char *current;
6370 while (*(current = args[idx++])) {
6371 err = invalid_char(current);
6372 if (err) {
6373 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6374 file, linenum, *err, item, current);
6375 return ERR_ALERT | ERR_FATAL;
6376 }
6377
6378 if (netns_store_lookup(current, strlen(current))) {
6379 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6380 file, linenum, current);
6381 return ERR_ALERT | ERR_FATAL;
6382 }
6383 if (!netns_store_insert(current)) {
6384 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6385 file, linenum, current);
6386 return ERR_ALERT | ERR_FATAL;
6387 }
6388 }
6389 }
6390
6391 return 0;
6392#else
6393 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6394 file, linenum);
6395 return ERR_ALERT | ERR_FATAL;
6396#endif
6397}
6398
6399int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006400cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6401{
6402
6403 int err_code = 0;
6404 const char *err;
6405
6406 if (!strcmp(args[0], "userlist")) { /* new userlist */
6407 struct userlist *newul;
6408
6409 if (!*args[1]) {
6410 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6411 file, linenum, args[0]);
6412 err_code |= ERR_ALERT | ERR_FATAL;
6413 goto out;
6414 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006415 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6416 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006417
6418 err = invalid_char(args[1]);
6419 if (err) {
6420 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6421 file, linenum, *err, args[0], args[1]);
6422 err_code |= ERR_ALERT | ERR_FATAL;
6423 goto out;
6424 }
6425
6426 for (newul = userlist; newul; newul = newul->next)
6427 if (!strcmp(newul->name, args[1])) {
6428 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6429 file, linenum, args[1]);
6430 err_code |= ERR_WARN;
6431 goto out;
6432 }
6433
6434 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6435 if (!newul) {
6436 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6437 err_code |= ERR_ALERT | ERR_ABORT;
6438 goto out;
6439 }
6440
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006441 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006442 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006443 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6444 err_code |= ERR_ALERT | ERR_ABORT;
6445 goto out;
6446 }
6447
6448 newul->next = userlist;
6449 userlist = newul;
6450
6451 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006452 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006453 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006454 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006455
6456 if (!*args[1]) {
6457 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6458 file, linenum, args[0]);
6459 err_code |= ERR_ALERT | ERR_FATAL;
6460 goto out;
6461 }
6462
6463 err = invalid_char(args[1]);
6464 if (err) {
6465 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6466 file, linenum, *err, args[0], args[1]);
6467 err_code |= ERR_ALERT | ERR_FATAL;
6468 goto out;
6469 }
6470
William Lallemand4ac9f542015-05-28 18:03:51 +02006471 if (!userlist)
6472 goto out;
6473
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006474 for (ag = userlist->groups; ag; ag = ag->next)
6475 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006476 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6477 file, linenum, args[1], userlist->name);
6478 err_code |= ERR_ALERT;
6479 goto out;
6480 }
6481
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006482 ag = calloc(1, sizeof(*ag));
6483 if (!ag) {
6484 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6485 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006486 goto out;
6487 }
6488
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006489 ag->name = strdup(args[1]);
6490 if (!ag) {
6491 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6492 err_code |= ERR_ALERT | ERR_ABORT;
6493 goto out;
6494 }
6495
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006496 cur_arg = 2;
6497
6498 while (*args[cur_arg]) {
6499 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006500 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006501 cur_arg += 2;
6502 continue;
6503 } else {
6504 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6505 file, linenum, args[0]);
6506 err_code |= ERR_ALERT | ERR_FATAL;
6507 goto out;
6508 }
6509 }
6510
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006511 ag->next = userlist->groups;
6512 userlist->groups = ag;
6513
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006514 } else if (!strcmp(args[0], "user")) { /* new user */
6515 struct auth_users *newuser;
6516 int cur_arg;
6517
6518 if (!*args[1]) {
6519 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6520 file, linenum, args[0]);
6521 err_code |= ERR_ALERT | ERR_FATAL;
6522 goto out;
6523 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006524 if (!userlist)
6525 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006526
6527 for (newuser = userlist->users; newuser; newuser = newuser->next)
6528 if (!strcmp(newuser->user, args[1])) {
6529 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6530 file, linenum, args[1], userlist->name);
6531 err_code |= ERR_ALERT;
6532 goto out;
6533 }
6534
6535 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6536 if (!newuser) {
6537 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6538 err_code |= ERR_ALERT | ERR_ABORT;
6539 goto out;
6540 }
6541
6542 newuser->user = strdup(args[1]);
6543
6544 newuser->next = userlist->users;
6545 userlist->users = newuser;
6546
6547 cur_arg = 2;
6548
6549 while (*args[cur_arg]) {
6550 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006551#ifdef CONFIG_HAP_CRYPT
6552 if (!crypt("", args[cur_arg + 1])) {
6553 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6554 file, linenum, newuser->user);
6555 err_code |= ERR_ALERT | ERR_FATAL;
6556 goto out;
6557 }
6558#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006559 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6560 file, linenum);
6561 err_code |= ERR_ALERT;
6562#endif
6563 newuser->pass = strdup(args[cur_arg + 1]);
6564 cur_arg += 2;
6565 continue;
6566 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6567 newuser->pass = strdup(args[cur_arg + 1]);
6568 newuser->flags |= AU_O_INSECURE;
6569 cur_arg += 2;
6570 continue;
6571 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006572 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006573 cur_arg += 2;
6574 continue;
6575 } else {
6576 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6577 file, linenum, args[0]);
6578 err_code |= ERR_ALERT | ERR_FATAL;
6579 goto out;
6580 }
6581 }
6582 } else {
6583 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6584 err_code |= ERR_ALERT | ERR_FATAL;
6585 }
6586
6587out:
6588 return err_code;
6589}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006590
6591/*
6592 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006593 * Returns the error code, 0 if OK, or any combination of :
6594 * - ERR_ABORT: must abort ASAP
6595 * - ERR_FATAL: we can continue parsing but not start the service
6596 * - ERR_WARN: a warning has been emitted
6597 * - ERR_ALERT: an alert has been emitted
6598 * Only the two first ones can stop processing, the two others are just
6599 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006600 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006601int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006602{
William Lallemand64e84512015-05-12 14:25:37 +02006603 char *thisline;
6604 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 FILE *f;
6606 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006607 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006608 struct cfg_section *cs = NULL;
6609 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006610 int readbytes = 0;
6611
6612 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006613 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006614 return -1;
6615 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006616
6617 /* Register internal sections */
6618 if (!cfg_register_section("listen", cfg_parse_listen) ||
6619 !cfg_register_section("frontend", cfg_parse_listen) ||
6620 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006621 !cfg_register_section("defaults", cfg_parse_listen) ||
6622 !cfg_register_section("global", cfg_parse_global) ||
6623 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006624 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006625 !cfg_register_section("mailers", cfg_parse_mailers) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006626 !cfg_register_section("namespace_list", cfg_parse_netns))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006627 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006628
Willy Tarreaubaaee002006-06-26 02:48:02 +02006629 if ((f=fopen(file,"r")) == NULL)
6630 return -1;
6631
William Lallemandb2f07452015-05-12 14:27:13 +02006632next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006633 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006634 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006635 char *end;
6636 char *args[MAX_LINE_ARGS + 1];
6637 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006638 int dquote = 0; /* double quote */
6639 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006640
Willy Tarreaubaaee002006-06-26 02:48:02 +02006641 linenum++;
6642
6643 end = line + strlen(line);
6644
William Lallemand64e84512015-05-12 14:25:37 +02006645 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006646 /* Check if we reached the limit and the last char is not \n.
6647 * Watch out for the last line without the terminating '\n'!
6648 */
William Lallemand64e84512015-05-12 14:25:37 +02006649 char *newline;
6650 int newlinesize = linesize * 2;
6651
6652 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6653 if (newline == NULL) {
6654 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6655 file, linenum);
6656 err_code |= ERR_ALERT | ERR_FATAL;
6657 continue;
6658 }
6659
6660 readbytes = linesize - 1;
6661 linesize = newlinesize;
6662 thisline = newline;
6663 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006664 }
6665
William Lallemand64e84512015-05-12 14:25:37 +02006666 readbytes = 0;
6667
Willy Tarreaubaaee002006-06-26 02:48:02 +02006668 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006669 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006670 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006671
Willy Tarreaubaaee002006-06-26 02:48:02 +02006672 arg = 0;
6673 args[arg] = line;
6674
6675 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006676 if (*line == '"' && !squote) { /* double quote outside single quotes */
6677 if (dquote)
6678 dquote = 0;
6679 else
6680 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006681 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006682 end--;
6683 }
6684 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6685 if (squote)
6686 squote = 0;
6687 else
6688 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006689 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006690 end--;
6691 }
6692 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006693 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6694 * C equivalent value. Other combinations left unchanged (eg: \1).
6695 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006696 int skip = 0;
6697 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6698 *line = line[1];
6699 skip = 1;
6700 }
6701 else if (line[1] == 'r') {
6702 *line = '\r';
6703 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006704 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006705 else if (line[1] == 'n') {
6706 *line = '\n';
6707 skip = 1;
6708 }
6709 else if (line[1] == 't') {
6710 *line = '\t';
6711 skip = 1;
6712 }
6713 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01006714 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006715 unsigned char hex1, hex2;
6716 hex1 = toupper(line[2]) - '0';
6717 hex2 = toupper(line[3]) - '0';
6718 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
6719 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
6720 *line = (hex1<<4) + hex2;
6721 skip = 3;
6722 }
6723 else {
6724 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006725 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006726 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006727 } else if (line[1] == '"') {
6728 *line = '"';
6729 skip = 1;
6730 } else if (line[1] == '\'') {
6731 *line = '\'';
6732 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02006733 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
6734 *line = '$';
6735 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006736 }
6737 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01006738 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006739 end -= skip;
6740 }
6741 line++;
6742 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006743 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006744 /* end of string, end of loop */
6745 *line = 0;
6746 break;
6747 }
William Lallemandf9873ba2015-05-05 17:37:14 +02006748 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006749 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006750 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006751 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006752 line++;
6753 args[++arg] = line;
6754 }
William Lallemandb2f07452015-05-12 14:27:13 +02006755 else if (dquote && *line == '$') {
6756 /* environment variables are evaluated inside double quotes */
6757 char *var_beg;
6758 char *var_end;
6759 char save_char;
6760 char *value;
6761 int val_len;
6762 int newlinesize;
6763 int braces = 0;
6764
6765 var_beg = line + 1;
6766 var_end = var_beg;
6767
6768 if (*var_beg == '{') {
6769 var_beg++;
6770 var_end++;
6771 braces = 1;
6772 }
6773
6774 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
6775 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
6776 err_code |= ERR_ALERT | ERR_FATAL;
6777 goto next_line; /* skip current line */
6778 }
6779
6780 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
6781 var_end++;
6782
6783 save_char = *var_end;
6784 *var_end = '\0';
6785 value = getenv(var_beg);
6786 *var_end = save_char;
6787 val_len = value ? strlen(value) : 0;
6788
6789 if (braces) {
6790 if (*var_end == '}') {
6791 var_end++;
6792 braces = 0;
6793 } else {
6794 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
6795 err_code |= ERR_ALERT | ERR_FATAL;
6796 goto next_line; /* skip current line */
6797 }
6798 }
6799
6800 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
6801
6802 /* if not enough space in thisline */
6803 if (newlinesize > linesize) {
6804 char *newline;
6805
6806 newline = realloc(thisline, newlinesize * sizeof(*thisline));
6807 if (newline == NULL) {
6808 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
6809 err_code |= ERR_ALERT | ERR_FATAL;
6810 goto next_line; /* slip current line */
6811 }
6812 /* recompute pointers if realloc returns a new pointer */
6813 if (newline != thisline) {
6814 int i;
6815 int diff;
6816
6817 for (i = 0; i <= arg; i++) {
6818 diff = args[i] - thisline;
6819 args[i] = newline + diff;
6820 }
6821
6822 diff = var_end - thisline;
6823 var_end = newline + diff;
6824 diff = end - thisline;
6825 end = newline + diff;
6826 diff = line - thisline;
6827 line = newline + diff;
6828 thisline = newline;
6829 }
6830 linesize = newlinesize;
6831 }
6832
6833 /* insert value inside the line */
6834 memmove(line + val_len, var_end, end - var_end + 1);
6835 memcpy(line, value, val_len);
6836 end += val_len - (var_end - line);
6837 line += val_len;
6838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006839 else {
6840 line++;
6841 }
6842 }
William Lallemandb2f07452015-05-12 14:27:13 +02006843
William Lallemandf9873ba2015-05-05 17:37:14 +02006844 if (dquote) {
6845 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
6846 err_code |= ERR_ALERT | ERR_FATAL;
6847 }
6848
6849 if (squote) {
6850 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
6851 err_code |= ERR_ALERT | ERR_FATAL;
6852 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006853
6854 /* empty line */
6855 if (!**args)
6856 continue;
6857
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006858 if (*line) {
6859 /* we had to stop due to too many args.
6860 * Let's terminate the string, print the offending part then cut the
6861 * last arg.
6862 */
6863 while (*line && *line != '#' && *line != '\n' && *line != '\r')
6864 line++;
6865 *line = '\0';
6866
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01006867 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01006868 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01006869 err_code |= ERR_ALERT | ERR_FATAL;
6870 args[arg] = line;
6871 }
6872
Willy Tarreau540abe42007-05-02 20:50:16 +02006873 /* zero out remaining args and ensure that at least one entry
6874 * is zeroed out.
6875 */
6876 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006877 args[arg] = line;
6878 }
6879
Willy Tarreau3842f002009-06-14 11:39:52 +02006880 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006881 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006882 char *tmp;
6883
Willy Tarreau3842f002009-06-14 11:39:52 +02006884 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02006885 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006886 for (arg=0; *args[arg+1]; arg++)
6887 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02006888 *tmp = '\0'; // fix the next arg to \0
6889 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006890 }
Willy Tarreau3842f002009-06-14 11:39:52 +02006891 else if (!strcmp(args[0], "default")) {
6892 kwm = KWM_DEF;
6893 for (arg=0; *args[arg+1]; arg++)
6894 args[arg] = args[arg+1]; // shift args after inversion
6895 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006896
William Lallemand0f99e342011-10-12 17:50:54 +02006897 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
6898 strcmp(args[0], "log") != 0) {
6899 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02006900 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01006901 }
6902
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006903 /* detect section start */
6904 list_for_each_entry(ics, &sections, list) {
6905 if (strcmp(args[0], ics->section_name) == 0) {
6906 cursection = ics->section_name;
6907 cs = ics;
6908 break;
6909 }
Emeric Brun32da3c42010-09-23 18:39:19 +02006910 }
6911
Willy Tarreaubaaee002006-06-26 02:48:02 +02006912 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006913 if (cs)
6914 err_code |= cs->section_parser(file, linenum, args, kwm);
6915 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006916 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02006917 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006918 }
Willy Tarreau058e9072009-07-20 09:30:05 +02006919
6920 if (err_code & ERR_ABORT)
6921 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006922 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01006923 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02006924 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006925 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02006926 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006927}
6928
Willy Tarreau64ab6072014-09-16 12:17:36 +02006929/* This function propagates processes from frontend <from> to backend <to> so
6930 * that it is always guaranteed that a backend pointed to by a frontend is
6931 * bound to all of its processes. After that, if the target is a "listen"
6932 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02006933 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02006934 * checked first to ensure that <to> is already bound to all processes of
6935 * <from>, there is no risk of looping and we ensure to follow the shortest
6936 * path to the destination.
6937 *
6938 * It is possible to set <to> to NULL for the first call so that the function
6939 * takes care of visiting the initial frontend in <from>.
6940 *
6941 * It is important to note that the function relies on the fact that all names
6942 * have already been resolved.
6943 */
6944void propagate_processes(struct proxy *from, struct proxy *to)
6945{
6946 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006947
6948 if (to) {
6949 /* check whether we need to go down */
6950 if (from->bind_proc &&
6951 (from->bind_proc & to->bind_proc) == from->bind_proc)
6952 return;
6953
6954 if (!from->bind_proc && !to->bind_proc)
6955 return;
6956
6957 to->bind_proc = from->bind_proc ?
6958 (to->bind_proc | from->bind_proc) : 0;
6959
6960 /* now propagate down */
6961 from = to;
6962 }
6963
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01006964 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02006965 return;
6966
Willy Tarreauf6b70012014-12-18 14:00:43 +01006967 if (from->state == PR_STSTOPPED)
6968 return;
6969
Willy Tarreau64ab6072014-09-16 12:17:36 +02006970 /* default_backend */
6971 if (from->defbe.be)
6972 propagate_processes(from, from->defbe.be);
6973
6974 /* use_backend */
6975 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02006976 if (rule->dynamic)
6977 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02006978 to = rule->be.backend;
6979 propagate_processes(from, to);
6980 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02006981}
6982
Willy Tarreaubb925012009-07-23 13:36:36 +02006983/*
6984 * Returns the error code, 0 if OK, or any combination of :
6985 * - ERR_ABORT: must abort ASAP
6986 * - ERR_FATAL: we can continue parsing but not start the service
6987 * - ERR_WARN: a warning has been emitted
6988 * - ERR_ALERT: an alert has been emitted
6989 * Only the two first ones can stop processing, the two others are just
6990 * indicators.
6991 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02006992int check_config_validity()
6993{
6994 int cfgerr = 0;
6995 struct proxy *curproxy = NULL;
6996 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02006997 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02006998 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02006999 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007000
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007001 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007002 /*
7003 * Now, check for the integrity of all that we have collected.
7004 */
7005
7006 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007007 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008
Willy Tarreau193b8c62012-11-22 00:17:38 +01007009 if (!global.tune.max_http_hdr)
7010 global.tune.max_http_hdr = MAX_HTTP_HDR;
7011
7012 if (!global.tune.cookie_len)
7013 global.tune.cookie_len = CAPTURE_LEN;
7014
7015 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7016
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007017 /* Post initialisation of the users and groups lists. */
7018 err_code = userlist_postinit();
7019 if (err_code != ERR_NONE)
7020 goto out;
7021
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007022 /* first, we will invert the proxy list order */
7023 curproxy = NULL;
7024 while (proxy) {
7025 struct proxy *next;
7026
7027 next = proxy->next;
7028 proxy->next = curproxy;
7029 curproxy = proxy;
7030 if (!next)
7031 break;
7032 proxy = next;
7033 }
7034
Willy Tarreau419ead82014-09-16 13:41:21 +02007035 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007036 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007037 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007038 struct sticking_rule *mrule;
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007039 struct tcp_rule *trule;
Willy Tarreau09448f72014-06-25 18:12:15 +02007040 struct http_req_rule *hrqrule;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007041 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007042 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007043
Willy Tarreau050536d2012-10-04 08:47:34 +02007044 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007045 /* proxy ID not set, use automatic numbering with first
7046 * spare entry starting with next_pxid.
7047 */
7048 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7049 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7050 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007051 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007052 next_pxid++;
7053
Willy Tarreau55ea7572007-06-17 19:56:27 +02007054
Willy Tarreaubaaee002006-06-26 02:48:02 +02007055 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007056 /* ensure we don't keep listeners uselessly bound */
7057 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007058 free((void *)curproxy->table.peers.name);
7059 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007060 continue;
7061 }
7062
Willy Tarreau102df612014-05-07 23:56:38 +02007063 /* Check multi-process mode compatibility for the current proxy */
7064
7065 if (curproxy->bind_proc) {
7066 /* an explicit bind-process was specified, let's check how many
7067 * processes remain.
7068 */
7069 nbproc = popcount(curproxy->bind_proc);
7070
7071 curproxy->bind_proc &= nbits(global.nbproc);
7072 if (!curproxy->bind_proc && nbproc == 1) {
7073 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);
7074 curproxy->bind_proc = 1;
7075 }
7076 else if (!curproxy->bind_proc && nbproc > 1) {
7077 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);
7078 curproxy->bind_proc = 0;
7079 }
7080 }
7081
Willy Tarreau3d209582014-05-09 17:06:11 +02007082 /* check and reduce the bind-proc of each listener */
7083 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7084 unsigned long mask;
7085
7086 if (!bind_conf->bind_proc)
7087 continue;
7088
7089 mask = nbits(global.nbproc);
7090 if (curproxy->bind_proc)
7091 mask &= curproxy->bind_proc;
7092 /* mask cannot be null here thanks to the previous checks */
7093
7094 nbproc = popcount(bind_conf->bind_proc);
7095 bind_conf->bind_proc &= mask;
7096
7097 if (!bind_conf->bind_proc && nbproc == 1) {
7098 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",
7099 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7100 bind_conf->bind_proc = mask & ~(mask - 1);
7101 }
7102 else if (!bind_conf->bind_proc && nbproc > 1) {
7103 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",
7104 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7105 bind_conf->bind_proc = 0;
7106 }
7107 }
7108
Willy Tarreauff01a212009-03-15 13:46:16 +01007109 switch (curproxy->mode) {
7110 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007111 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007112 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007113 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7114 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007115 cfgerr++;
7116 }
7117
7118 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007119 Warning("config : servers will be ignored for %s '%s'.\n",
7120 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007121 break;
7122
7123 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007124 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007125 break;
7126
7127 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007128 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007129 break;
7130 }
7131
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007132 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007133 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007134 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007135 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7136 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007137 cfgerr++;
7138 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007139#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007140 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007141 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7142 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007143 cfgerr++;
7144 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007145#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007146 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007147 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7148 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007149 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007150 }
7151 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007152 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007153 /* If no LB algo is set in a backend, and we're not in
7154 * transparent mode, dispatch mode nor proxy mode, we
7155 * want to use balance roundrobin by default.
7156 */
7157 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7158 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007159 }
7160 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007161
Willy Tarreau1620ec32011-08-06 17:05:02 +02007162 if (curproxy->options & PR_O_DISPATCH)
7163 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7164 else if (curproxy->options & PR_O_HTTP_PROXY)
7165 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7166 else if (curproxy->options & PR_O_TRANSP)
7167 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007168
Willy Tarreau1620ec32011-08-06 17:05:02 +02007169 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7170 if (curproxy->options & PR_O_DISABLE404) {
7171 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7172 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7173 err_code |= ERR_WARN;
7174 curproxy->options &= ~PR_O_DISABLE404;
7175 }
7176 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7177 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7178 "send-state", proxy_type_str(curproxy), curproxy->id);
7179 err_code |= ERR_WARN;
7180 curproxy->options &= ~PR_O2_CHK_SNDST;
7181 }
Willy Tarreauef781042010-01-27 11:53:01 +01007182 }
7183
Simon Horman98637e52014-06-20 12:30:16 +09007184 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7185 if (!global.external_check) {
7186 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7187 curproxy->id, "option external-check");
7188 cfgerr++;
7189 }
7190 if (!curproxy->check_command) {
7191 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7192 curproxy->id, "option external-check");
7193 cfgerr++;
7194 }
7195 }
7196
Simon Horman64e34162015-02-06 11:11:57 +09007197 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007198 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7199 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Simon Horman64e34162015-02-06 11:11:57 +09007200 "'email-alert from', 'email-alert level' 'email-alert mailer', "
7201 "'email-alert hostname', or 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007202 "requrires each of 'email-alert from', 'email-alert mailer' and 'email-alert' "
7203 "to be present).\n",
7204 proxy_type_str(curproxy), curproxy->id);
7205 err_code |= ERR_WARN;
7206 free_email_alert(curproxy);
7207 }
7208 if (!curproxy->email_alert.myhostname)
7209 curproxy->email_alert.myhostname = hostname;
Simon Horman9dc49962015-01-30 11:22:59 +09007210 }
7211
Simon Horman98637e52014-06-20 12:30:16 +09007212 if (curproxy->check_command) {
7213 int clear = 0;
7214 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7215 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7216 "external-check command", proxy_type_str(curproxy), curproxy->id);
7217 err_code |= ERR_WARN;
7218 clear = 1;
7219 }
7220 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
7221 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-command path' is not set.\n",
7222 curproxy->id, "external-check command");
7223 cfgerr++;
7224 }
7225 if (clear) {
7226 free(curproxy->check_command);
7227 curproxy->check_command = NULL;
7228 }
7229 }
7230
7231 if (curproxy->check_path) {
7232 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7233 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7234 "external-check path", proxy_type_str(curproxy), curproxy->id);
7235 err_code |= ERR_WARN;
7236 free(curproxy->check_path);
7237 curproxy->check_path = NULL;
7238 }
7239 }
7240
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007241 /* if a default backend was specified, let's find it */
7242 if (curproxy->defbe.name) {
7243 struct proxy *target;
7244
Willy Tarreauafb39922015-05-26 12:04:09 +02007245 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007246 if (!target) {
7247 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7248 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007249 cfgerr++;
7250 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007251 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7252 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007253 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007254 } else if (target->mode != curproxy->mode &&
7255 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7256
7257 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7258 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7259 curproxy->conf.file, curproxy->conf.line,
7260 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7261 target->conf.file, target->conf.line);
7262 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007263 } else {
7264 free(curproxy->defbe.name);
7265 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007266
7267 /* Emit a warning if this proxy also has some servers */
7268 if (curproxy->srv) {
7269 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7270 curproxy->id);
7271 err_code |= ERR_WARN;
7272 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007273 }
7274 }
7275
Willy Tarreau55ea7572007-06-17 19:56:27 +02007276 /* find the target proxy for 'use_backend' rules */
7277 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007278 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007279 struct logformat_node *node;
7280 char *pxname;
7281
7282 /* Try to parse the string as a log format expression. If the result
7283 * of the parsing is only one entry containing a simple string, then
7284 * it's a standard string corresponding to a static rule, thus the
7285 * parsing is cancelled and be.name is restored to be resolved.
7286 */
7287 pxname = rule->be.name;
7288 LIST_INIT(&rule->be.expr);
7289 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7290 curproxy->conf.args.file, curproxy->conf.args.line);
7291 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7292
7293 if (!LIST_ISEMPTY(&rule->be.expr)) {
7294 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7295 rule->dynamic = 1;
7296 free(pxname);
7297 continue;
7298 }
7299 /* simple string: free the expression and fall back to static rule */
7300 free(node->arg);
7301 free(node);
7302 }
7303
7304 rule->dynamic = 0;
7305 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007306
Willy Tarreauafb39922015-05-26 12:04:09 +02007307 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007308 if (!target) {
7309 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7310 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007311 cfgerr++;
7312 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007313 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7314 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007315 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007316 } else if (target->mode != curproxy->mode &&
7317 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7318
7319 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7320 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7321 curproxy->conf.file, curproxy->conf.line,
7322 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7323 target->conf.file, target->conf.line);
7324 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007325 } else {
7326 free((void *)rule->be.name);
7327 rule->be.backend = target;
7328 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007329 }
7330
Willy Tarreau64ab6072014-09-16 12:17:36 +02007331 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007332 list_for_each_entry(srule, &curproxy->server_rules, list) {
7333 struct server *target = findserver(curproxy, srule->srv.name);
7334
7335 if (!target) {
7336 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7337 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7338 cfgerr++;
7339 continue;
7340 }
7341 free((void *)srule->srv.name);
7342 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007343 }
7344
Emeric Brunb982a3d2010-01-04 15:45:53 +01007345 /* find the target table for 'stick' rules */
7346 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7347 struct proxy *target;
7348
Emeric Brun1d33b292010-01-04 15:47:17 +01007349 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7350 if (mrule->flags & STK_IS_STORE)
7351 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7352
Emeric Brunb982a3d2010-01-04 15:45:53 +01007353 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007354 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007355 else
7356 target = curproxy;
7357
7358 if (!target) {
7359 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7360 curproxy->id, mrule->table.name);
7361 cfgerr++;
7362 }
7363 else if (target->table.size == 0) {
7364 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7365 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7366 cfgerr++;
7367 }
Willy Tarreau12785782012-04-27 21:37:17 +02007368 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7369 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007370 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7371 cfgerr++;
7372 }
7373 else {
7374 free((void *)mrule->table.name);
7375 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007376 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007377 }
7378 }
7379
7380 /* find the target table for 'store response' rules */
7381 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7382 struct proxy *target;
7383
Emeric Brun1d33b292010-01-04 15:47:17 +01007384 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7385
Emeric Brunb982a3d2010-01-04 15:45:53 +01007386 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007387 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007388 else
7389 target = curproxy;
7390
7391 if (!target) {
7392 Alert("Proxy '%s': unable to find store table '%s'.\n",
7393 curproxy->id, mrule->table.name);
7394 cfgerr++;
7395 }
7396 else if (target->table.size == 0) {
7397 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7398 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7399 cfgerr++;
7400 }
Willy Tarreau12785782012-04-27 21:37:17 +02007401 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7402 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007403 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7404 cfgerr++;
7405 }
7406 else {
7407 free((void *)mrule->table.name);
7408 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007409 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007410 }
7411 }
7412
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007413 /* find the target table for 'tcp-request' layer 4 rules */
7414 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7415 struct proxy *target;
7416
Willy Tarreaub4c84932013-07-23 19:15:30 +02007417 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007418 continue;
7419
7420 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007421 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007422 else
7423 target = curproxy;
7424
7425 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007426 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7427 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007428 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007429 cfgerr++;
7430 }
7431 else if (target->table.size == 0) {
7432 Alert("Proxy '%s': table '%s' used but not configured.\n",
7433 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7434 cfgerr++;
7435 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007436 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7437 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7438 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 +01007439 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007440 cfgerr++;
7441 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007442 else {
7443 free(trule->act_prm.trk_ctr.table.n);
7444 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007445 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007446 * to pass a list of counters to track and allocate them right here using
7447 * stktable_alloc_data_type().
7448 */
7449 }
7450 }
7451
Willy Tarreaud1f96522010-08-03 19:34:32 +02007452 /* find the target table for 'tcp-request' layer 6 rules */
7453 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7454 struct proxy *target;
7455
Willy Tarreaub4c84932013-07-23 19:15:30 +02007456 if (trule->action < TCP_ACT_TRK_SC0 || trule->action > TCP_ACT_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007457 continue;
7458
7459 if (trule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007460 target = proxy_tbl_by_name(trule->act_prm.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007461 else
7462 target = curproxy;
7463
7464 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007465 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7466 curproxy->id, trule->act_prm.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007467 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007468 cfgerr++;
7469 }
7470 else if (target->table.size == 0) {
7471 Alert("Proxy '%s': table '%s' used but not configured.\n",
7472 curproxy->id, trule->act_prm.trk_ctr.table.n ? trule->act_prm.trk_ctr.table.n : curproxy->id);
7473 cfgerr++;
7474 }
Willy Tarreau5f53de72012-12-12 00:25:44 +01007475 else if (!stktable_compatible_sample(trule->act_prm.trk_ctr.expr, target->table.type)) {
7476 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7477 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 +01007478 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007479 cfgerr++;
7480 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007481 else {
7482 free(trule->act_prm.trk_ctr.table.n);
7483 trule->act_prm.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007484 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007485 * to pass a list of counters to track and allocate them right here using
7486 * stktable_alloc_data_type().
7487 */
7488 }
7489 }
7490
Willy Tarreau09448f72014-06-25 18:12:15 +02007491 /* find the target table for 'http-request' layer 7 rules */
7492 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7493 struct proxy *target;
7494
7495 if (hrqrule->action < HTTP_REQ_ACT_TRK_SC0 || hrqrule->action > HTTP_REQ_ACT_TRK_SCMAX)
7496 continue;
7497
7498 if (hrqrule->act_prm.trk_ctr.table.n)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007499 target = proxy_tbl_by_name(hrqrule->act_prm.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007500 else
7501 target = curproxy;
7502
7503 if (!target) {
7504 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7505 curproxy->id, hrqrule->act_prm.trk_ctr.table.n,
7506 http_req_trk_idx(hrqrule->action));
7507 cfgerr++;
7508 }
7509 else if (target->table.size == 0) {
7510 Alert("Proxy '%s': table '%s' used but not configured.\n",
7511 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id);
7512 cfgerr++;
7513 }
7514 else if (!stktable_compatible_sample(hrqrule->act_prm.trk_ctr.expr, target->table.type)) {
7515 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7516 curproxy->id, hrqrule->act_prm.trk_ctr.table.n ? hrqrule->act_prm.trk_ctr.table.n : curproxy->id,
7517 http_req_trk_idx(hrqrule->action));
7518 cfgerr++;
7519 }
7520 else {
7521 free(hrqrule->act_prm.trk_ctr.table.n);
7522 hrqrule->act_prm.trk_ctr.table.t = &target->table;
7523 /* Note: if we decide to enhance the track-sc syntax, we may be able
7524 * to pass a list of counters to track and allocate them right here using
7525 * stktable_alloc_data_type().
7526 */
7527 }
7528 }
7529
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007530 /* move any "block" rules at the beginning of the http-request rules */
7531 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7532 /* insert block_rules into http_req_rules at the beginning */
7533 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7534 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7535 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7536 curproxy->http_req_rules.n = curproxy->block_rules.n;
7537 LIST_INIT(&curproxy->block_rules);
7538 }
7539
Emeric Brun32da3c42010-09-23 18:39:19 +02007540 if (curproxy->table.peers.name) {
7541 struct peers *curpeers = peers;
7542
7543 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7544 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7545 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007546 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007547 break;
7548 }
7549 }
7550
7551 if (!curpeers) {
7552 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7553 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007554 free((void *)curproxy->table.peers.name);
7555 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007556 cfgerr++;
7557 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007558 else if (curpeers->state == PR_STSTOPPED) {
7559 /* silently disable this peers section */
7560 curproxy->table.peers.p = NULL;
7561 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007562 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007563 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7564 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007565 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007566 cfgerr++;
7567 }
7568 }
7569
Simon Horman9dc49962015-01-30 11:22:59 +09007570
7571 if (curproxy->email_alert.mailers.name) {
7572 struct mailers *curmailers = mailers;
7573
7574 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7575 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7576 free(curproxy->email_alert.mailers.name);
7577 curproxy->email_alert.mailers.m = curmailers;
7578 curmailers->users++;
7579 break;
7580 }
7581 }
7582
7583 if (!curmailers) {
7584 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7585 curproxy->id, curproxy->email_alert.mailers.name);
7586 free_email_alert(curproxy);
7587 cfgerr++;
7588 }
7589 }
7590
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007591 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007592 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007593 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7594 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7595 "proxy", curproxy->id);
7596 cfgerr++;
7597 goto out_uri_auth_compat;
7598 }
7599
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007600 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007601 const char *uri_auth_compat_req[10];
Willy Tarreauff011f22011-01-06 17:51:27 +01007602 struct http_req_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007603 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007604
Willy Tarreau95fa4692010-02-01 13:05:50 +01007605 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7606 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007607
7608 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007609 uri_auth_compat_req[i++] = "realm";
7610 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7611 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007612
Willy Tarreau95fa4692010-02-01 13:05:50 +01007613 uri_auth_compat_req[i++] = "unless";
7614 uri_auth_compat_req[i++] = "{";
7615 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7616 uri_auth_compat_req[i++] = "}";
7617 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007618
Willy Tarreauff011f22011-01-06 17:51:27 +01007619 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7620 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007621 cfgerr++;
7622 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007623 }
7624
Willy Tarreauff011f22011-01-06 17:51:27 +01007625 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007626
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007627 if (curproxy->uri_auth->auth_realm) {
7628 free(curproxy->uri_auth->auth_realm);
7629 curproxy->uri_auth->auth_realm = NULL;
7630 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007631
7632 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007633 }
7634out_uri_auth_compat:
7635
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007636 /* compile the log format */
7637 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007638 if (curproxy->conf.logformat_string != default_http_log_format &&
7639 curproxy->conf.logformat_string != default_tcp_log_format &&
7640 curproxy->conf.logformat_string != clf_http_log_format)
7641 free(curproxy->conf.logformat_string);
7642 curproxy->conf.logformat_string = NULL;
7643 free(curproxy->conf.lfs_file);
7644 curproxy->conf.lfs_file = NULL;
7645 curproxy->conf.lfs_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007646 }
7647
Willy Tarreau62a61232013-04-12 18:13:46 +02007648 if (curproxy->conf.logformat_string) {
7649 curproxy->conf.args.ctx = ARGC_LOG;
7650 curproxy->conf.args.file = curproxy->conf.lfs_file;
7651 curproxy->conf.args.line = curproxy->conf.lfs_line;
7652 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007653 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007654 curproxy->conf.args.file = NULL;
7655 curproxy->conf.args.line = 0;
7656 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007657
Willy Tarreau62a61232013-04-12 18:13:46 +02007658 if (curproxy->conf.uniqueid_format_string) {
7659 curproxy->conf.args.ctx = ARGC_UIF;
7660 curproxy->conf.args.file = curproxy->conf.uif_file;
7661 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01007662 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08007663 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007664 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007665 curproxy->conf.args.file = NULL;
7666 curproxy->conf.args.line = 0;
7667 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007668
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007669 /* only now we can check if some args remain unresolved.
7670 * This must be done after the users and groups resolution.
7671 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007672 cfgerr += smp_resolve_args(curproxy);
7673 if (!cfgerr)
7674 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01007675
Willy Tarreau2738a142006-07-08 17:28:09 +02007676 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007677 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02007678 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02007679 (!curproxy->timeout.connect ||
7680 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007681 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02007682 " | While not properly invalid, you will certainly encounter various problems\n"
7683 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01007684 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007685 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007686 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02007687 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02007688
Willy Tarreau1fa31262007-12-03 00:36:16 +01007689 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
7690 * We must still support older configurations, so let's find out whether those
7691 * parameters have been set or must be copied from contimeouts.
7692 */
7693 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007694 if (!curproxy->timeout.tarpit ||
7695 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007696 /* tarpit timeout not set. We search in the following order:
7697 * default.tarpit, curr.connect, default.connect.
7698 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007699 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007700 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007701 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007702 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007703 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007704 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007705 }
7706 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007707 (!curproxy->timeout.queue ||
7708 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01007709 /* queue timeout not set. We search in the following order:
7710 * default.queue, curr.connect, default.connect.
7711 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007712 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01007713 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007714 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007715 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02007716 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01007717 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01007718 }
7719 }
7720
Willy Tarreau1620ec32011-08-06 17:05:02 +02007721 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01007722 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
7723 curproxy->check_req = (char *)malloc(curproxy->check_len);
7724 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02007725 }
7726
Willy Tarreau215663d2014-06-13 18:30:23 +02007727 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
7728 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
7729 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
7730 proxy_type_str(curproxy), curproxy->id);
7731 err_code |= ERR_WARN;
7732 }
7733
Willy Tarreau193b8c62012-11-22 00:17:38 +01007734 /* ensure that cookie capture length is not too large */
7735 if (curproxy->capture_len >= global.tune.cookie_len) {
7736 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
7737 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
7738 err_code |= ERR_WARN;
7739 curproxy->capture_len = global.tune.cookie_len - 1;
7740 }
7741
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007742 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01007743 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007744 curproxy->req_cap_pool = create_pool("ptrcap",
7745 curproxy->nb_req_cap * sizeof(char *),
7746 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007747 }
7748
7749 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02007750 curproxy->rsp_cap_pool = create_pool("ptrcap",
7751 curproxy->nb_rsp_cap * sizeof(char *),
7752 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01007753 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02007754
Willy Tarreaubaaee002006-06-26 02:48:02 +02007755 /* first, we will invert the servers list order */
7756 newsrv = NULL;
7757 while (curproxy->srv) {
7758 struct server *next;
7759
7760 next = curproxy->srv->next;
7761 curproxy->srv->next = newsrv;
7762 newsrv = curproxy->srv;
7763 if (!next)
7764 break;
7765 curproxy->srv = next;
7766 }
7767
Willy Tarreau17edc812014-01-03 12:14:34 +01007768 /* Check that no server name conflicts. This causes trouble in the stats.
7769 * We only emit a warning for the first conflict affecting each server,
7770 * in order to avoid combinatory explosion if all servers have the same
7771 * name. We do that only for servers which do not have an explicit ID,
7772 * because these IDs were made also for distinguishing them and we don't
7773 * want to annoy people who correctly manage them.
7774 */
7775 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
7776 struct server *other_srv;
7777
7778 if (newsrv->puid)
7779 continue;
7780
7781 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
7782 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
7783 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
7784 newsrv->conf.file, newsrv->conf.line,
7785 proxy_type_str(curproxy), curproxy->id,
7786 newsrv->id, other_srv->conf.line);
7787 break;
7788 }
7789 }
7790 }
7791
Willy Tarreaudd701652010-05-25 23:03:02 +02007792 /* assign automatic UIDs to servers which don't have one yet */
7793 next_id = 1;
7794 newsrv = curproxy->srv;
7795 while (newsrv != NULL) {
7796 if (!newsrv->puid) {
7797 /* server ID not set, use automatic numbering with first
7798 * spare entry starting with next_svid.
7799 */
7800 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
7801 newsrv->conf.id.key = newsrv->puid = next_id;
7802 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
7803 }
7804 next_id++;
7805 newsrv = newsrv->next;
7806 }
7807
Willy Tarreau20697042007-11-15 23:26:18 +01007808 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01007809 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007810
Willy Tarreau62c3be22012-01-20 13:12:32 +01007811 /*
7812 * If this server supports a maxconn parameter, it needs a dedicated
7813 * tasks to fill the emptied slots when a connection leaves.
7814 * Also, resolve deferred tracking dependency if needed.
7815 */
7816 newsrv = curproxy->srv;
7817 while (newsrv != NULL) {
7818 if (newsrv->minconn > newsrv->maxconn) {
7819 /* Only 'minconn' was specified, or it was higher than or equal
7820 * to 'maxconn'. Let's turn this into maxconn and clean it, as
7821 * this will avoid further useless expensive computations.
7822 */
7823 newsrv->maxconn = newsrv->minconn;
7824 } else if (newsrv->maxconn && !newsrv->minconn) {
7825 /* minconn was not specified, so we set it to maxconn */
7826 newsrv->minconn = newsrv->maxconn;
7827 }
7828
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007829#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02007830 if (newsrv->use_ssl || newsrv->check.use_ssl)
7831 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02007832#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02007833
Willy Tarreau2f075e92013-12-03 11:11:34 +01007834 /* set the check type on the server */
7835 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
7836
Willy Tarreau62c3be22012-01-20 13:12:32 +01007837 if (newsrv->trackit) {
7838 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02007839 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007840 char *pname, *sname;
7841
7842 pname = newsrv->trackit;
7843 sname = strrchr(pname, '/');
7844
7845 if (sname)
7846 *sname++ = '\0';
7847 else {
7848 sname = pname;
7849 pname = NULL;
7850 }
7851
7852 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007853 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007854 if (!px) {
7855 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
7856 proxy_type_str(curproxy), curproxy->id,
7857 newsrv->id, pname);
7858 cfgerr++;
7859 goto next_srv;
7860 }
7861 } else
7862 px = curproxy;
7863
7864 srv = findserver(px, sname);
7865 if (!srv) {
7866 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
7867 proxy_type_str(curproxy), curproxy->id,
7868 newsrv->id, sname);
7869 cfgerr++;
7870 goto next_srv;
7871 }
7872
Willy Tarreau32091232014-05-16 13:52:00 +02007873 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
7874 !(srv->agent.state & CHK_ST_CONFIGURED) &&
7875 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01007876 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02007877 "tracking as it does not have any check nor agent enabled.\n",
7878 proxy_type_str(curproxy), curproxy->id,
7879 newsrv->id, px->id, srv->id);
7880 cfgerr++;
7881 goto next_srv;
7882 }
7883
7884 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
7885
7886 if (loop) {
7887 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
7888 "belongs to a tracking chain looping back to %s/%s.\n",
7889 proxy_type_str(curproxy), curproxy->id,
7890 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01007891 cfgerr++;
7892 goto next_srv;
7893 }
7894
7895 if (curproxy != px &&
7896 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
7897 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
7898 "tracking: disable-on-404 option inconsistency.\n",
7899 proxy_type_str(curproxy), curproxy->id,
7900 newsrv->id, px->id, srv->id);
7901 cfgerr++;
7902 goto next_srv;
7903 }
7904
7905 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02007906 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02007907 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02007908 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09007909 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007910 }
7911
7912 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01007913 newsrv->tracknext = srv->trackers;
7914 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01007915
7916 free(newsrv->trackit);
7917 newsrv->trackit = NULL;
7918 }
7919 next_srv:
7920 newsrv = newsrv->next;
7921 }
7922
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007923 /* We have to initialize the server lookup mechanism depending
7924 * on what LB algorithm was choosen.
7925 */
7926
7927 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
7928 switch (curproxy->lbprm.algo & BE_LB_KIND) {
7929 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02007930 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
7931 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7932 init_server_map(curproxy);
7933 } else {
7934 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
7935 fwrr_init_server_groups(curproxy);
7936 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007937 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007938
Willy Tarreau3ebb1162012-02-13 16:57:44 +01007939 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01007940 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
7941 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
7942 fwlc_init_server_tree(curproxy);
7943 } else {
7944 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
7945 fas_init_server_tree(curproxy);
7946 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007947 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007948
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007949 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02007950 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
7951 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
7952 chash_init_server_tree(curproxy);
7953 } else {
7954 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
7955 init_server_map(curproxy);
7956 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007957 break;
7958 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007959
7960 if (curproxy->options & PR_O_LOGASAP)
7961 curproxy->to_log &= ~LW_BYTES;
7962
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007963 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreaud79a3b22012-12-28 09:40:16 +01007964 (curproxy->cap & PR_CAP_FE) && !LIST_ISEMPTY(&curproxy->logformat) && LIST_ISEMPTY(&curproxy->logsrvs)) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02007965 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
7966 proxy_type_str(curproxy), curproxy->id);
7967 err_code |= ERR_WARN;
7968 }
7969
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007970 if (curproxy->mode != PR_MODE_HTTP) {
7971 int optnum;
7972
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007973 if (curproxy->uri_auth) {
7974 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
7975 proxy_type_str(curproxy), curproxy->id);
7976 err_code |= ERR_WARN;
7977 curproxy->uri_auth = NULL;
7978 }
7979
Willy Tarreau87cf5142011-08-19 22:57:24 +02007980 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007981 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7982 "forwardfor", proxy_type_str(curproxy), curproxy->id);
7983 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02007984 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01007985 }
7986
7987 if (curproxy->options & PR_O_ORGTO) {
7988 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7989 "originalto", proxy_type_str(curproxy), curproxy->id);
7990 err_code |= ERR_WARN;
7991 curproxy->options &= ~PR_O_ORGTO;
7992 }
7993
7994 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
7995 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
7996 (curproxy->cap & cfg_opts[optnum].cap) &&
7997 (curproxy->options & cfg_opts[optnum].val)) {
7998 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
7999 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8000 err_code |= ERR_WARN;
8001 curproxy->options &= ~cfg_opts[optnum].val;
8002 }
8003 }
8004
8005 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8006 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8007 (curproxy->cap & cfg_opts2[optnum].cap) &&
8008 (curproxy->options2 & cfg_opts2[optnum].val)) {
8009 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8010 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8011 err_code |= ERR_WARN;
8012 curproxy->options2 &= ~cfg_opts2[optnum].val;
8013 }
8014 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008015
Pieter Baauwd551fb52013-05-08 22:49:23 +02008016#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008017 if (curproxy->conn_src.bind_hdr_occ) {
8018 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008019 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008020 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008021 err_code |= ERR_WARN;
8022 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008023#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008024 }
8025
Willy Tarreaubaaee002006-06-26 02:48:02 +02008026 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008027 * ensure that we're not cross-dressing a TCP server into HTTP.
8028 */
8029 newsrv = curproxy->srv;
8030 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008031 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008032 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8033 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008034 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008035 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008036
Willy Tarreau0cec3312011-10-31 13:49:26 +01008037 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8038 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8039 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8040 err_code |= ERR_WARN;
8041 }
8042
Willy Tarreauc93cd162014-05-13 15:54:22 +02008043 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008044 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8045 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8046 err_code |= ERR_WARN;
8047 }
8048
Pieter Baauwd551fb52013-05-08 22:49:23 +02008049#if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008050 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8051 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008052 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 +01008053 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008054 err_code |= ERR_WARN;
8055 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008056#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008057 newsrv = newsrv->next;
8058 }
8059
Willy Tarreaue42bd962014-09-16 16:21:19 +02008060 /* check if we have a frontend with "tcp-request content" looking at L7
8061 * with no inspect-delay
8062 */
8063 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8064 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
8065 if (trule->action == TCP_ACT_CAPTURE &&
8066 !(trule->act_prm.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8067 break;
8068 if ((trule->action >= TCP_ACT_TRK_SC0 && trule->action <= TCP_ACT_TRK_SCMAX) &&
8069 !(trule->act_prm.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
8070 break;
8071 }
8072
8073 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8074 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8075 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8076 " This means that these rules will randomly find their contents. This can be fixed by"
8077 " setting the tcp-request inspect-delay.\n",
8078 proxy_type_str(curproxy), curproxy->id);
8079 err_code |= ERR_WARN;
8080 }
8081 }
8082
Willy Tarreauc1a21672009-08-16 22:37:44 +02008083 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008084 if (!curproxy->accept)
8085 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008086
Willy Tarreauc1a21672009-08-16 22:37:44 +02008087 if (curproxy->tcp_req.inspect_delay ||
8088 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008089 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008090
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008091 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008092 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008093 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008094 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008095
8096 /* both TCP and HTTP must check switching rules */
8097 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
8098 }
8099
8100 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008101 if (curproxy->tcp_req.inspect_delay ||
8102 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8103 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8104
Emeric Brun97679e72010-09-23 17:56:44 +02008105 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8106 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8107
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008108 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008109 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008110 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008111 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008112
8113 /* If the backend does requires RDP cookie persistence, we have to
8114 * enable the corresponding analyser.
8115 */
8116 if (curproxy->options2 & PR_O2_RDPC_PRST)
8117 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
8118 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008119 }
8120
8121 /***********************************************************/
8122 /* At this point, target names have already been resolved. */
8123 /***********************************************************/
8124
8125 /* Check multi-process mode compatibility */
8126
8127 if (global.nbproc > 1 && global.stats_fe) {
8128 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8129 unsigned long mask;
8130
8131 mask = nbits(global.nbproc);
8132 if (global.stats_fe->bind_proc)
8133 mask &= global.stats_fe->bind_proc;
8134
8135 if (bind_conf->bind_proc)
8136 mask &= bind_conf->bind_proc;
8137
8138 /* stop here if more than one process is used */
8139 if (popcount(mask) > 1)
8140 break;
8141 }
8142 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8143 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");
8144 }
8145 }
8146
8147 /* Make each frontend inherit bind-process from its listeners when not specified. */
8148 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8149 if (curproxy->bind_proc)
8150 continue;
8151
8152 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8153 unsigned long mask;
8154
Willy Tarreaue428b082015-05-04 21:57:58 +02008155 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008156 curproxy->bind_proc |= mask;
8157 }
8158
8159 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008160 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008161 }
8162
8163 if (global.stats_fe) {
8164 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8165 unsigned long mask;
8166
Willy Tarreaue428b082015-05-04 21:57:58 +02008167 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008168 global.stats_fe->bind_proc |= mask;
8169 }
8170 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008171 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008172 }
8173
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008174 /* propagate bindings from frontends to backends. Don't do it if there
8175 * are any fatal errors as we must not call it with unresolved proxies.
8176 */
8177 if (!cfgerr) {
8178 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8179 if (curproxy->cap & PR_CAP_FE)
8180 propagate_processes(curproxy, NULL);
8181 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008182 }
8183
8184 /* Bind each unbound backend to all processes when not specified. */
8185 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8186 if (curproxy->bind_proc)
8187 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008188 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008189 }
8190
8191 /*******************************************************/
8192 /* At this step, all proxies have a non-null bind_proc */
8193 /*******************************************************/
8194
8195 /* perform the final checks before creating tasks */
8196
8197 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8198 struct listener *listener;
8199 unsigned int next_id;
8200 int nbproc;
8201
8202 nbproc = popcount(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008203
Emeric Brunc52962f2012-11-15 18:28:02 +01008204#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008205 /* Configure SSL for each bind line.
8206 * Note: if configuration fails at some point, the ->ctx member
8207 * remains NULL so that listeners can later detach.
8208 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008209 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008210 int alloc_ctx;
8211
Emeric Brunc52962f2012-11-15 18:28:02 +01008212 if (!bind_conf->is_ssl) {
8213 if (bind_conf->default_ctx) {
8214 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8215 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8216 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008217 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008218 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008219 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008220 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008221 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008222 cfgerr++;
8223 continue;
8224 }
8225
Emeric Brun8dc60392014-05-09 13:52:00 +02008226 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008227 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008228 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8229 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");
8230 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008231 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008232 cfgerr++;
8233 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008234 }
8235
Emeric Brunfc0421f2012-09-07 17:30:07 +02008236 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008237 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008238
8239 /* initialize CA variables if the certificates generation is enabled */
8240 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008241 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008242#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008243
Willy Tarreaue6b98942007-10-29 01:09:36 +01008244 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008245 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008246 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008247 if (!listener->luid) {
8248 /* listener ID not set, use automatic numbering with first
8249 * spare entry starting with next_luid.
8250 */
8251 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8252 listener->conf.id.key = listener->luid = next_id;
8253 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008254 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008255 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008256
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008257 /* enable separate counters */
8258 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8259 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008260 if (!listener->name)
8261 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008262 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008263
Willy Tarreaue6b98942007-10-29 01:09:36 +01008264 if (curproxy->options & PR_O_TCP_NOLING)
8265 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008266 if (!listener->maxconn)
8267 listener->maxconn = curproxy->maxconn;
8268 if (!listener->backlog)
8269 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008270 if (!listener->maxaccept)
8271 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8272
8273 /* we want to have an optimal behaviour on single process mode to
8274 * maximize the work at once, but in multi-process we want to keep
8275 * some fairness between processes, so we target half of the max
8276 * number of events to be balanced over all the processes the proxy
8277 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8278 * used to disable the limit.
8279 */
8280 if (listener->maxaccept > 0) {
8281 if (nbproc > 1)
8282 listener->maxaccept = (listener->maxaccept + 1) / 2;
8283 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8284 }
8285
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008286 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008287 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008288 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008289 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008290
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008291 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8292 listener->options |= LI_O_TCP_RULES;
8293
Willy Tarreaude3041d2010-05-31 10:56:17 +02008294 if (curproxy->mon_mask.s_addr)
8295 listener->options |= LI_O_CHK_MONNET;
8296
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008297 /* smart accept mode is automatic in HTTP mode */
8298 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008299 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008300 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8301 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008302 }
8303
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008304 /* Release unused SSL configs */
8305 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8306 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008307 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008308#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008309 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008310 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008311 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008312 free(bind_conf->ca_sign_file);
8313 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008314 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008315 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008316 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008317 if(bind_conf->keys_ref) {
8318 free(bind_conf->keys_ref->filename);
8319 free(bind_conf->keys_ref->tlskeys);
8320 free(bind_conf->keys_ref);
8321 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008322#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008323 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008324
Willy Tarreau102df612014-05-07 23:56:38 +02008325 if (nbproc > 1) {
8326 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008327 int count, maxproc = 0;
8328
8329 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8330 count = popcount(bind_conf->bind_proc);
8331 if (count > maxproc)
8332 maxproc = count;
8333 }
8334 /* backends have 0, frontends have 1 or more */
8335 if (maxproc != 1)
8336 Warning("Proxy '%s': in multi-process mode, stats will be"
8337 " limited to process assigned to the current request.\n",
8338 curproxy->id);
8339
Willy Tarreau102df612014-05-07 23:56:38 +02008340 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8341 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8342 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008343 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008344 }
Willy Tarreau102df612014-05-07 23:56:38 +02008345 if (curproxy->appsession_name) {
8346 Warning("Proxy '%s': appsession will not work correctly in multi-process mode.\n",
8347 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008348 }
Willy Tarreau102df612014-05-07 23:56:38 +02008349 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8350 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8351 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008352 }
8353 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008354
8355 /* create the task associated with the proxy */
8356 curproxy->task = task_new();
8357 if (curproxy->task) {
8358 curproxy->task->context = curproxy;
8359 curproxy->task->process = manage_proxy;
8360 /* no need to queue, it will be done automatically if some
8361 * listener gets limited.
8362 */
8363 curproxy->task->expire = TICK_ETERNITY;
8364 } else {
8365 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8366 curproxy->id);
8367 cfgerr++;
8368 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008369 }
8370
Willy Tarreaufbb78422011-06-05 15:38:35 +02008371 /* automatically compute fullconn if not set. We must not do it in the
8372 * loop above because cross-references are not yet fully resolved.
8373 */
8374 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8375 /* If <fullconn> is not set, let's set it to 10% of the sum of
8376 * the possible incoming frontend's maxconns.
8377 */
8378 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8379 struct proxy *fe;
8380 int total = 0;
8381
8382 /* sum up the number of maxconns of frontends which
8383 * reference this backend at least once or which are
8384 * the same one ('listen').
8385 */
8386 for (fe = proxy; fe; fe = fe->next) {
8387 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008388 int found = 0;
8389
8390 if (!(fe->cap & PR_CAP_FE))
8391 continue;
8392
8393 if (fe == curproxy) /* we're on a "listen" instance */
8394 found = 1;
8395
8396 if (fe->defbe.be == curproxy) /* "default_backend" */
8397 found = 1;
8398
8399 /* check if a "use_backend" rule matches */
8400 if (!found) {
8401 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008402 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008403 found = 1;
8404 break;
8405 }
8406 }
8407 }
8408
Willy Tarreaufbb78422011-06-05 15:38:35 +02008409 /* now we've checked all possible ways to reference a backend
8410 * from a frontend.
8411 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008412 if (!found)
8413 continue;
8414 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008415 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008416 /* we have the sum of the maxconns in <total>. We only
8417 * keep 10% of that sum to set the default fullconn, with
8418 * a hard minimum of 1 (to avoid a divide by zero).
8419 */
8420 curproxy->fullconn = (total + 9) / 10;
8421 if (!curproxy->fullconn)
8422 curproxy->fullconn = 1;
8423 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008424 }
8425
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008426 /*
8427 * Recount currently required checks.
8428 */
8429
8430 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8431 int optnum;
8432
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008433 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8434 if (curproxy->options & cfg_opts[optnum].val)
8435 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008436
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008437 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8438 if (curproxy->options2 & cfg_opts2[optnum].val)
8439 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008440 }
8441
Willy Tarreau0fca4832015-05-01 19:12:05 +02008442 /* compute the required process bindings for the peers */
8443 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8444 if (curproxy->table.peers.p)
8445 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8446
Willy Tarreau122541c2011-09-07 21:24:49 +02008447 if (peers) {
8448 struct peers *curpeers = peers, **last;
8449 struct peer *p, *pb;
8450
Willy Tarreau1e273012015-05-01 19:15:17 +02008451 /* Remove all peers sections which don't have a valid listener,
8452 * which are not used by any table, or which are bound to more
8453 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008454 */
8455 last = &peers;
8456 while (*last) {
8457 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008458
8459 if (curpeers->state == PR_STSTOPPED) {
8460 /* the "disabled" keyword was present */
8461 if (curpeers->peers_fe)
8462 stop_proxy(curpeers->peers_fe);
8463 curpeers->peers_fe = NULL;
8464 }
8465 else if (!curpeers->peers_fe) {
8466 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8467 curpeers->id, localpeer);
8468 }
Willy Tarreau1e273012015-05-01 19:15:17 +02008469 else if (popcount(curpeers->peers_fe->bind_proc) != 1) {
8470 /* either it's totally stopped or too much used */
8471 if (curpeers->peers_fe->bind_proc) {
8472 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008473 "running in different processes (%d different ones). "
8474 "Check global.nbproc and all tables' bind-process "
8475 "settings.\n", curpeers->id, popcount(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008476 cfgerr++;
8477 }
8478 stop_proxy(curpeers->peers_fe);
8479 curpeers->peers_fe = NULL;
8480 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008481 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008482 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008483 last = &curpeers->next;
8484 continue;
8485 }
8486
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008487 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008488 p = curpeers->remote;
8489 while (p) {
8490 pb = p->next;
8491 free(p->id);
8492 free(p);
8493 p = pb;
8494 }
8495
8496 /* Destroy and unlink this curpeers section.
8497 * Note: curpeers is backed up into *last.
8498 */
8499 free(curpeers->id);
8500 curpeers = curpeers->next;
8501 free(*last);
8502 *last = curpeers;
8503 }
8504 }
8505
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008506 /* initialize stick-tables on backend capable proxies. This must not
8507 * be done earlier because the data size may be discovered while parsing
8508 * other proxies.
8509 */
8510 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8511 if (curproxy->state == PR_STSTOPPED)
8512 continue;
8513
8514 if (!stktable_init(&curproxy->table)) {
8515 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8516 cfgerr++;
8517 }
8518 }
8519
Simon Horman0d16a402015-01-30 11:22:58 +09008520 if (mailers) {
8521 struct mailers *curmailers = mailers, **last;
8522 struct mailer *m, *mb;
8523
8524 /* Remove all mailers sections which don't have a valid listener.
8525 * This can happen when a mailers section is never referenced.
8526 */
8527 last = &mailers;
8528 while (*last) {
8529 curmailers = *last;
8530 if (curmailers->users) {
8531 last = &curmailers->next;
8532 continue;
8533 }
8534
8535 Warning("Removing incomplete section 'mailers %s'.\n",
8536 curmailers->id);
8537
8538 m = curmailers->mailer_list;
8539 while (m) {
8540 mb = m->next;
8541 free(m->id);
8542 free(m);
8543 m = mb;
8544 }
8545
8546 /* Destroy and unlink this curmailers section.
8547 * Note: curmailers is backed up into *last.
8548 */
8549 free(curmailers->id);
8550 curmailers = curmailers->next;
8551 free(*last);
8552 *last = curmailers;
8553 }
8554 }
8555
Willy Tarreau34eb6712011-10-24 18:15:04 +02008556 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008557 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008558 MEM_F_SHARED);
8559
Willy Tarreaubb925012009-07-23 13:36:36 +02008560 if (cfgerr > 0)
8561 err_code |= ERR_ALERT | ERR_FATAL;
8562 out:
8563 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008564}
8565
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008566/*
8567 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
8568 * parsing sessions.
8569 */
8570void cfg_register_keywords(struct cfg_kw_list *kwl)
8571{
8572 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
8573}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008574
Willy Tarreau5b2c3362008-07-09 19:39:06 +02008575/*
8576 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
8577 */
8578void cfg_unregister_keywords(struct cfg_kw_list *kwl)
8579{
8580 LIST_DEL(&kwl->list);
8581 LIST_INIT(&kwl->list);
8582}
Willy Tarreaubaaee002006-06-26 02:48:02 +02008583
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01008584/* this function register new section in the haproxy configuration file.
8585 * <section_name> is the name of this new section and <section_parser>
8586 * is the called parser. If two section declaration have the same name,
8587 * only the first declared is used.
8588 */
8589int cfg_register_section(char *section_name,
8590 int (*section_parser)(const char *, int, char **, int))
8591{
8592 struct cfg_section *cs;
8593
8594 cs = calloc(1, sizeof(*cs));
8595 if (!cs) {
8596 Alert("register section '%s': out of memory.\n", section_name);
8597 return 0;
8598 }
8599
8600 cs->section_name = section_name;
8601 cs->section_parser = section_parser;
8602
8603 LIST_ADDQ(&sections, &cs->list);
8604
8605 return 1;
8606}
8607
Willy Tarreaubaaee002006-06-26 02:48:02 +02008608/*
8609 * Local variables:
8610 * c-indent-level: 8
8611 * c-basic-offset: 8
8612 * End:
8613 */