blob: d44f57a43ff25e4808e53d382ec2db89cf450263 [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>
Christopher Fauletd7c91962015-04-30 11:48:27 +020048#include <types/filters.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020049#include <types/global.h>
Willy Tarreau3fdb3662012-11-12 00:42:33 +010050#include <types/obj_type.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020051#include <types/peers.h>
Simon Horman0d16a402015-01-30 11:22:58 +090052#include <types/mailers.h>
Baptiste Assmann325137d2015-04-13 23:40:55 +020053#include <types/dns.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020054
Willy Tarreaueb0c6142007-05-07 00:53:22 +020055#include <proto/acl.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010056#include <proto/auth.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020057#include <proto/backend.h>
Willy Tarreauc7e42382012-08-24 19:22:53 +020058#include <proto/channel.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020059#include <proto/checks.h>
William Lallemand82fe75c2012-10-23 10:25:10 +020060#include <proto/compression.h>
Willy Tarreaufbee7132007-10-18 13:53:22 +020061#include <proto/dumpstats.h>
Christopher Fauletd7c91962015-04-30 11:48:27 +020062#include <proto/filters.h>
Willy Tarreaueb472682010-05-28 18:46:57 +020063#include <proto/frontend.h>
Willy Tarreau34eb6712011-10-24 18:15:04 +020064#include <proto/hdr_idx.h>
Willy Tarreau6b2e11b2009-10-01 07:52:15 +020065#include <proto/lb_chash.h>
Willy Tarreauf09c6602012-02-13 17:12:08 +010066#include <proto/lb_fas.h>
Willy Tarreauf89c1872009-10-01 11:19:37 +020067#include <proto/lb_fwlc.h>
68#include <proto/lb_fwrr.h>
69#include <proto/lb_map.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020070#include <proto/listener.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020071#include <proto/log.h>
Willy Tarreaud1d54542012-09-12 22:58:11 +020072#include <proto/protocol.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010073#include <proto/proto_tcp.h>
Emeric Bruned760922010-10-22 17:59:25 +020074#include <proto/proto_uxst.h>
Willy Tarreaue6b98942007-10-29 01:09:36 +010075#include <proto/proto_http.h>
Willy Tarreau2b5652f2006-12-31 17:46:05 +010076#include <proto/proxy.h>
Emeric Brun32da3c42010-09-23 18:39:19 +020077#include <proto/peers.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020078#include <proto/sample.h>
Willy Tarreau9903f0e2015-04-04 18:50:31 +020079#include <proto/session.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020080#include <proto/server.h>
Willy Tarreau87b09662015-04-03 00:22:06 +020081#include <proto/stream.h>
Willy Tarreau75bf2c92012-08-20 17:01:35 +020082#include <proto/raw_sock.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020083#include <proto/task.h>
Emeric Brunb982a3d2010-01-04 15:45:53 +010084#include <proto/stick_table.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020085
Emeric Brunfc0421f2012-09-07 17:30:07 +020086#ifdef USE_OPENSSL
87#include <types/ssl_sock.h>
88#include <proto/ssl_sock.h>
89#include <proto/shctx.h>
90#endif /*USE_OPENSSL */
Willy Tarreaubaaee002006-06-26 02:48:02 +020091
Willy Tarreauf3c69202006-07-09 16:42:34 +020092/* This is the SSLv3 CLIENT HELLO packet used in conjunction with the
93 * ssl-hello-chk option to ensure that the remote server speaks SSL.
94 *
95 * Check RFC 2246 (TLSv1.0) sections A.3 and A.4 for details.
96 */
97const char sslv3_client_hello_pkt[] = {
98 "\x16" /* ContentType : 0x16 = Hanshake */
99 "\x03\x00" /* ProtocolVersion : 0x0300 = SSLv3 */
100 "\x00\x79" /* ContentLength : 0x79 bytes after this one */
101 "\x01" /* HanshakeType : 0x01 = CLIENT HELLO */
102 "\x00\x00\x75" /* HandshakeLength : 0x75 bytes after this one */
103 "\x03\x00" /* Hello Version : 0x0300 = v3 */
104 "\x00\x00\x00\x00" /* Unix GMT Time (s) : filled with <now> (@0x0B) */
105 "HAPROXYSSLCHK\nHAPROXYSSLCHK\n" /* Random : must be exactly 28 bytes */
106 "\x00" /* Session ID length : empty (no session ID) */
107 "\x00\x4E" /* Cipher Suite Length : 78 bytes after this one */
108 "\x00\x01" "\x00\x02" "\x00\x03" "\x00\x04" /* 39 most common ciphers : */
109 "\x00\x05" "\x00\x06" "\x00\x07" "\x00\x08" /* 0x01...0x1B, 0x2F...0x3A */
110 "\x00\x09" "\x00\x0A" "\x00\x0B" "\x00\x0C" /* This covers RSA/DH, */
111 "\x00\x0D" "\x00\x0E" "\x00\x0F" "\x00\x10" /* various bit lengths, */
112 "\x00\x11" "\x00\x12" "\x00\x13" "\x00\x14" /* SHA1/MD5, DES/3DES/AES... */
113 "\x00\x15" "\x00\x16" "\x00\x17" "\x00\x18"
114 "\x00\x19" "\x00\x1A" "\x00\x1B" "\x00\x2F"
115 "\x00\x30" "\x00\x31" "\x00\x32" "\x00\x33"
116 "\x00\x34" "\x00\x35" "\x00\x36" "\x00\x37"
117 "\x00\x38" "\x00\x39" "\x00\x3A"
118 "\x01" /* Compression Length : 0x01 = 1 byte for types */
119 "\x00" /* Compression Type : 0x00 = NULL compression */
120};
121
Willy Tarreau3842f002009-06-14 11:39:52 +0200122/* various keyword modifiers */
123enum kw_mod {
124 KWM_STD = 0, /* normal */
125 KWM_NO, /* "no" prefixed before the keyword */
126 KWM_DEF, /* "default" prefixed before the keyword */
127};
128
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +0100129/* permit to store configuration section */
130struct cfg_section {
131 struct list list;
132 char *section_name;
133 int (*section_parser)(const char *, int, char **, int);
134};
135
136/* Used to chain configuration sections definitions. This list
137 * stores struct cfg_section
138 */
139struct list sections = LIST_HEAD_INIT(sections);
140
Willy Tarreau13943ab2006-12-31 00:24:10 +0100141/* some of the most common options which are also the easiest to handle */
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100142struct cfg_opt {
Willy Tarreau13943ab2006-12-31 00:24:10 +0100143 const char *name;
144 unsigned int val;
145 unsigned int cap;
Willy Tarreau4fee4e92007-01-06 21:09:17 +0100146 unsigned int checks;
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100147 unsigned int mode;
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100148};
149
150/* proxy->options */
151static const struct cfg_opt cfg_opts[] =
Willy Tarreau13943ab2006-12-31 00:24:10 +0100152{
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100153 { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0, 0 },
154 { "allbackups", PR_O_USE_ALL_BK, PR_CAP_BE, 0, 0 },
155 { "checkcache", PR_O_CHK_CACHE, PR_CAP_BE, 0, PR_MODE_HTTP },
156 { "clitcpka", PR_O_TCP_CLI_KA, PR_CAP_FE, 0, 0 },
157 { "contstats", PR_O_CONTSTATS, PR_CAP_FE, 0, 0 },
158 { "dontlognull", PR_O_NULLNOLOG, PR_CAP_FE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100159 { "http_proxy", PR_O_HTTP_PROXY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau9fbe18e2015-05-01 22:42:08 +0200160 { "http-buffer-request", PR_O_WREQ_BODY, PR_CAP_FE | PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau0f228a02015-05-01 15:37:53 +0200161 { "http-ignore-probes", PR_O_IGNORE_PRB, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreau9420b122013-12-15 18:58:25 +0100162 { "prefer-last-server", PR_O_PREF_LAST, PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100163 { "logasap", PR_O_LOGASAP, PR_CAP_FE, 0, 0 },
164 { "nolinger", PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0, 0 },
165 { "persist", PR_O_PERSIST, PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100166 { "srvtcpka", PR_O_TCP_SRV_KA, PR_CAP_BE, 0, 0 },
Krzysztof Oledzki336d4752007-12-25 02:40:22 +0100167#ifdef TPROXY
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100168 { "transparent", PR_O_TRANSP, PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100169#else
170 { "transparent", 0, 0, 0, 0 },
Willy Tarreau8f922fc2007-01-06 21:11:49 +0100171#endif
172
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100173 { NULL, 0, 0, 0, 0 }
Willy Tarreau13943ab2006-12-31 00:24:10 +0100174};
175
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100176/* proxy->options2 */
177static const struct cfg_opt cfg_opts2[] =
178{
179#ifdef CONFIG_HAP_LINUX_SPLICE
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100180 { "splice-request", PR_O2_SPLIC_REQ, PR_CAP_FE|PR_CAP_BE, 0, 0 },
181 { "splice-response", PR_O2_SPLIC_RTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
182 { "splice-auto", PR_O2_SPLIC_AUT, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Cyril Bonté62846b22010-11-01 19:26:00 +0100183#else
184 { "splice-request", 0, 0, 0, 0 },
185 { "splice-response", 0, 0, 0, 0 },
186 { "splice-auto", 0, 0, 0, 0 },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100187#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100188 { "accept-invalid-http-request", PR_O2_REQBUG_OK, PR_CAP_FE, 0, PR_MODE_HTTP },
189 { "accept-invalid-http-response", PR_O2_RSPBUG_OK, PR_CAP_BE, 0, PR_MODE_HTTP },
190 { "dontlog-normal", PR_O2_NOLOGNORM, PR_CAP_FE, 0, 0 },
191 { "log-separate-errors", PR_O2_LOGERRORS, PR_CAP_FE, 0, 0 },
192 { "log-health-checks", PR_O2_LOGHCHKS, PR_CAP_BE, 0, 0 },
193 { "socket-stats", PR_O2_SOCKSTAT, PR_CAP_FE, 0, 0 },
194 { "tcp-smart-accept", PR_O2_SMARTACC, PR_CAP_FE, 0, 0 },
195 { "tcp-smart-connect", PR_O2_SMARTCON, PR_CAP_BE, 0, 0 },
196 { "independant-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Jamie Gloudon801a0a32012-08-25 00:18:33 -0400197 { "independent-streams", PR_O2_INDEPSTR, PR_CAP_FE|PR_CAP_BE, 0, 0 },
Willy Tarreaue24fdfb2010-03-25 07:22:56 +0100198 { "http-use-proxy-header", PR_O2_USE_PXHDR, PR_CAP_FE, 0, PR_MODE_HTTP },
Willy Tarreaue52564c2010-04-27 22:19:14 +0200199 { "http-pretend-keepalive", PR_O2_FAKE_KA, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau96e31212011-05-30 18:10:30 +0200200 { "http-no-delay", PR_O2_NODELAY, PR_CAP_FE|PR_CAP_BE, 0, PR_MODE_HTTP },
Willy Tarreau66aa61f2009-01-18 21:44:07 +0100201 { NULL, 0, 0, 0 }
202};
Willy Tarreaubaaee002006-06-26 02:48:02 +0200203
Willy Tarreau6daf3432008-01-22 16:44:08 +0100204static char *cursection = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200205static struct proxy defproxy; /* fake proxy used to assign default values on all instances */
206int cfg_maxpconn = DEFAULT_MAXCONN; /* # of simultaneous connections per proxy (-N) */
Willy Tarreau5af24ef2009-03-15 15:23:16 +0100207int cfg_maxconn = 0; /* # of simultaneous connections, (-n) */
Willy Tarreaubaaee002006-06-26 02:48:02 +0200208
Willy Tarreau5b2c3362008-07-09 19:39:06 +0200209/* List head of all known configuration keywords */
210static struct cfg_kw_list cfg_keywords = {
211 .list = LIST_HEAD_INIT(cfg_keywords.list)
212};
213
Willy Tarreaubaaee002006-06-26 02:48:02 +0200214/*
215 * converts <str> to a list of listeners which are dynamically allocated.
216 * The format is "{addr|'*'}:port[-end][,{addr|'*'}:port[-end]]*", where :
217 * - <addr> can be empty or "*" to indicate INADDR_ANY ;
218 * - <port> is a numerical port from 1 to 65535 ;
219 * - <end> indicates to use the range from <port> to <end> instead (inclusive).
220 * This can be repeated as many times as necessary, separated by a coma.
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200221 * Function returns 1 for success or 0 if error. In case of errors, if <err> is
222 * not NULL, it must be a valid pointer to either NULL or a freeable area that
223 * will be replaced with an error message.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 */
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200225int 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 +0200226{
227 struct listener *l;
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100228 char *next, *dupstr;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200229 int port, end;
230
231 next = dupstr = strdup(str);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200232
Willy Tarreaubaaee002006-06-26 02:48:02 +0200233 while (next && *next) {
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100234 struct sockaddr_storage ss, *ss2;
Willy Tarreau40aa0702013-03-10 23:51:38 +0100235 int fd = -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200236
237 str = next;
238 /* 1) look for the end of the first address */
Krzysztof Piotr Oledzki52d522b2009-01-27 16:57:08 +0100239 if ((next = strchr(str, ',')) != NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200240 *next++ = 0;
241 }
242
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100243 ss2 = str2sa_range(str, &port, &end, err,
Willy Tarreau72b8c1f2015-09-08 15:50:19 +0200244 curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +0200245 NULL, 1);
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100246 if (!ss2)
247 goto fail;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200248
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100249 if (ss2->ss_family == AF_INET || ss2->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100250 if (!port && !end) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200251 memprintf(err, "missing port number: '%s'\n", str);
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100252 goto fail;
Emeric Bruned760922010-10-22 17:59:25 +0200253 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200254
Willy Tarreau6d03cc32013-02-20 17:26:02 +0100255 if (!port || !end) {
256 memprintf(err, "port offsets are not allowed in 'bind': '%s'\n", str);
257 goto fail;
258 }
259
Emeric Bruned760922010-10-22 17:59:25 +0200260 if (port < 1 || port > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200261 memprintf(err, "invalid port '%d' specified for address '%s'.\n", port, str);
Emeric Bruned760922010-10-22 17:59:25 +0200262 goto fail;
263 }
264
265 if (end < 1 || end > 65535) {
Willy Tarreau4fbb2282012-09-20 20:01:39 +0200266 memprintf(err, "invalid port '%d' specified for address '%s'.\n", end, str);
Emeric Bruned760922010-10-22 17:59:25 +0200267 goto fail;
268 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200269 }
Willy Tarreau40aa0702013-03-10 23:51:38 +0100270 else if (ss2->ss_family == AF_UNSPEC) {
271 socklen_t addr_len;
272
273 /* We want to attach to an already bound fd whose number
274 * is in the addr part of ss2 when cast to sockaddr_in.
275 * Note that by definition there is a single listener.
276 * We still have to determine the address family to
277 * register the correct protocol.
278 */
279 fd = ((struct sockaddr_in *)ss2)->sin_addr.s_addr;
280 addr_len = sizeof(*ss2);
281 if (getsockname(fd, (struct sockaddr *)ss2, &addr_len) == -1) {
282 memprintf(err, "cannot use file descriptor '%d' : %s.\n", fd, strerror(errno));
283 goto fail;
284 }
285
286 port = end = get_host_port(ss2);
287 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200288
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100289 /* OK the address looks correct */
290 ss = *ss2;
291
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 for (; port <= end; port++) {
293 l = (struct listener *)calloc(1, sizeof(struct listener));
Willy Tarreau3fdb3662012-11-12 00:42:33 +0100294 l->obj_type = OBJ_TYPE_LISTENER;
Willy Tarreau4348fad2012-09-20 16:48:07 +0200295 LIST_ADDQ(&curproxy->conf.listeners, &l->by_fe);
296 LIST_ADDQ(&bind_conf->listeners, &l->by_bind);
297 l->frontend = curproxy;
298 l->bind_conf = bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200299
Willy Tarreau40aa0702013-03-10 23:51:38 +0100300 l->fd = fd;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200301 l->addr = ss;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +0200302 l->xprt = &raw_sock;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100303 l->state = LI_INIT;
304
Willy Tarreau2dff0c22011-03-04 15:43:13 +0100305 if (ss.ss_family == AF_INET) {
Willy Tarreaubaaee002006-06-26 02:48:02 +0200306 ((struct sockaddr_in *)(&l->addr))->sin_port = htons(port);
Willy Tarreaue6b98942007-10-29 01:09:36 +0100307 tcpv4_add_listener(l);
308 }
Emeric Bruned760922010-10-22 17:59:25 +0200309 else if (ss.ss_family == AF_INET6) {
310 ((struct sockaddr_in6 *)(&l->addr))->sin6_port = htons(port);
311 tcpv6_add_listener(l);
312 }
313 else {
Emeric Bruned760922010-10-22 17:59:25 +0200314 uxst_add_listener(l);
315 }
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200316
Willy Tarreauaf7ad002010-08-31 15:39:26 +0200317 jobs++;
Willy Tarreaue6b98942007-10-29 01:09:36 +0100318 listeners++;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200319 } /* end for(port) */
320 } /* end while(next) */
321 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200322 return 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200323 fail:
324 free(dupstr);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +0200325 return 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200326}
327
William Lallemand6e62fb62015-04-28 16:55:23 +0200328/*
329 * Report a fatal Alert when there is too much arguments
330 * The index is the current keyword in args
331 * Return 0 if the number of argument is correct, otherwise emit an alert and return 1
332 * Fill err_code with an ERR_ALERT and an ERR_FATAL
333 */
334int alertif_too_many_args_idx(int maxarg, int index, const char *file, int linenum, char **args, int *err_code)
335{
336 char *kw = NULL;
337 int i;
338
339 if (!*args[index + maxarg + 1])
340 return 0;
341
342 memprintf(&kw, "%s", args[0]);
343 for (i = 1; i <= index; i++) {
344 memprintf(&kw, "%s %s", kw, args[i]);
345 }
346
347 Alert("parsing [%s:%d] : '%s' cannot handle unexpected argument '%s'.\n", file, linenum, kw, args[index + maxarg + 1]);
348 free(kw);
349 *err_code |= ERR_ALERT | ERR_FATAL;
350 return 1;
351}
352
353/*
354 * same as alertif_too_many_args_idx with a 0 index
355 */
356int alertif_too_many_args(int maxarg, const char *file, int linenum, char **args, int *err_code)
357{
358 return alertif_too_many_args_idx(maxarg, 0, file, linenum, args, err_code);
359}
360
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request content' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau61d18892009-03-31 10:49:21 +0200374/* Report a warning if a rule is placed after a 'block' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100377int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200378{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200379 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau5002f572014-04-23 01:32:02 +0200387/* Report a warning if a rule is placed after an 'http_request' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
390int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
391{
392 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
393 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau61d18892009-03-31 10:49:21 +0200400/* Report a warning if a rule is placed after a reqrewrite rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100403int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200404{
405 if (proxy->req_exp) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
413/* Report a warning if a rule is placed after a reqadd rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100418 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' rule will still be processed before.\n",
420 file, line, arg);
421 return 1;
422 }
423 return 0;
424}
425
426/* Report a warning if a rule is placed after a redirect rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
431 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
433 file, line, arg);
434 return 1;
435 }
436 return 0;
437}
438
439/* Report a warning if a rule is placed after a 'use_backend' rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
Willy Tarreauee445d92014-04-23 01:39:04 +0200452/* Report a warning if a rule is placed after a 'use-server' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
455int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
456{
457 if (!LIST_ISEMPTY(&proxy->server_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200465/* report a warning if a "tcp request connection" rule is dangerously placed */
466int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
467{
468 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
469 warnif_rule_after_block(proxy, file, line, arg) ||
470 warnif_rule_after_http_req(proxy, file, line, arg) ||
471 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
472 warnif_rule_after_reqadd(proxy, file, line, arg) ||
473 warnif_rule_after_redirect(proxy, file, line, arg) ||
474 warnif_rule_after_use_backend(proxy, file, line, arg) ||
475 warnif_rule_after_use_server(proxy, file, line, arg);
476}
477
478/* report a warning if a "tcp request content" rule is dangerously placed */
479int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
480{
481 return warnif_rule_after_block(proxy, file, line, arg) ||
482 warnif_rule_after_http_req(proxy, file, line, arg) ||
483 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
484 warnif_rule_after_reqadd(proxy, file, line, arg) ||
485 warnif_rule_after_redirect(proxy, file, line, arg) ||
486 warnif_rule_after_use_backend(proxy, file, line, arg) ||
487 warnif_rule_after_use_server(proxy, file, line, arg);
488}
489
Willy Tarreau61d18892009-03-31 10:49:21 +0200490/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100491int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200492{
Willy Tarreau5002f572014-04-23 01:32:02 +0200493 return warnif_rule_after_http_req(proxy, file, line, arg) ||
494 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
495 warnif_rule_after_reqadd(proxy, file, line, arg) ||
496 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200497 warnif_rule_after_use_backend(proxy, file, line, arg) ||
498 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200499}
500
501/* report a warning if an http-request rule is dangerously placed */
502int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
503{
Willy Tarreau61d18892009-03-31 10:49:21 +0200504 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
505 warnif_rule_after_reqadd(proxy, file, line, arg) ||
506 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200507 warnif_rule_after_use_backend(proxy, file, line, arg) ||
508 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200509}
510
511/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100512int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200513{
514 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
515 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200516 warnif_rule_after_use_backend(proxy, file, line, arg) ||
517 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200518}
519
520/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100521int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200522{
523 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200524 warnif_rule_after_use_backend(proxy, file, line, arg) ||
525 warnif_rule_after_use_server(proxy, file, line, arg);
526}
527
528/* report a warning if a redirect rule is dangerously placed */
529int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
530{
531 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
532 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200533}
534
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100535/* Report it if a request ACL condition uses some keywords that are incompatible
536 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
537 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
538 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100539 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100540static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100541{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100542 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200543 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100544
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100545 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100546 return 0;
547
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100548 acl = acl_cond_conflicts(cond, where);
549 if (acl) {
550 if (acl->name && *acl->name)
551 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
552 file, line, acl->name, sample_ckp_names(where));
553 else
554 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 +0200555 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100556 return ERR_WARN;
557 }
558 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100559 return 0;
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561 if (acl->name && *acl->name)
562 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200563 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100564 else
565 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200566 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100567 return ERR_WARN;
568}
569
Willy Tarreaubaaee002006-06-26 02:48:02 +0200570/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200571 * parse a line in a <global> section. Returns the error code, 0 if OK, or
572 * any combination of :
573 * - ERR_ABORT: must abort ASAP
574 * - ERR_FATAL: we can continue parsing but not start the service
575 * - ERR_WARN: a warning has been emitted
576 * - ERR_ALERT: an alert has been emitted
577 * Only the two first ones can stop processing, the two others are just
578 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200579 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200580int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200581{
Willy Tarreau058e9072009-07-20 09:30:05 +0200582 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200583 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200584
585 if (!strcmp(args[0], "global")) { /* new section */
586 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200587 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200588 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200589 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200590 else if (!strcmp(args[0], "ca-base")) {
591#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200592 if(alertif_too_many_args(1, file, linenum, args, &err_code))
593 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200594 if (global.ca_base != NULL) {
595 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
596 err_code |= ERR_ALERT;
597 goto out;
598 }
599 if (*(args[1]) == 0) {
600 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
601 err_code |= ERR_ALERT | ERR_FATAL;
602 goto out;
603 }
604 global.ca_base = strdup(args[1]);
605#else
606 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
607 err_code |= ERR_ALERT | ERR_FATAL;
608 goto out;
609#endif
610 }
611 else if (!strcmp(args[0], "crt-base")) {
612#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200613 if (alertif_too_many_args(1, file, linenum, args, &err_code))
614 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200615 if (global.crt_base != NULL) {
616 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
617 err_code |= ERR_ALERT;
618 goto out;
619 }
620 if (*(args[1]) == 0) {
621 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT | ERR_FATAL;
623 goto out;
624 }
625 global.crt_base = strdup(args[1]);
626#else
627 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
628 err_code |= ERR_ALERT | ERR_FATAL;
629 goto out;
630#endif
631 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200632 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200633 if (alertif_too_many_args(0, file, linenum, args, &err_code))
634 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200635 global.mode |= MODE_DAEMON;
636 }
637 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200638 if (alertif_too_many_args(0, file, linenum, args, &err_code))
639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200640 global.mode |= MODE_DEBUG;
641 }
642 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200643 if (alertif_too_many_args(0, file, linenum, args, &err_code))
644 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100645 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200646 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200647 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200648 if (alertif_too_many_args(0, file, linenum, args, &err_code))
649 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100650 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200651 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200652 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200653 if (alertif_too_many_args(0, file, linenum, args, &err_code))
654 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100655 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200656 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100657 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200658 if (alertif_too_many_args(0, file, linenum, args, &err_code))
659 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100660 global.tune.options &= ~GTUNE_USE_SPLICE;
661 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200662 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200663 if (alertif_too_many_args(0, file, linenum, args, &err_code))
664 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200665 global.tune.options &= ~GTUNE_USE_GAI;
666 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200667 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200668 if (alertif_too_many_args(0, file, linenum, args, &err_code))
669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200670 global.mode |= MODE_QUIET;
671 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200672 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200673 if (alertif_too_many_args(1, file, linenum, args, &err_code))
674 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200675 if (global.tune.maxpollevents != 0) {
676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200677 err_code |= ERR_ALERT;
678 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200679 }
680 if (*(args[1]) == 0) {
681 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200682 err_code |= ERR_ALERT | ERR_FATAL;
683 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200684 }
685 global.tune.maxpollevents = atol(args[1]);
686 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100687 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200688 if (alertif_too_many_args(1, file, linenum, args, &err_code))
689 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100690 if (global.tune.maxaccept != 0) {
691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200692 err_code |= ERR_ALERT;
693 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100694 }
695 if (*(args[1]) == 0) {
696 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200697 err_code |= ERR_ALERT | ERR_FATAL;
698 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100699 }
700 global.tune.maxaccept = atol(args[1]);
701 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200702 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200703 if (alertif_too_many_args(1, file, linenum, args, &err_code))
704 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200705 if (*(args[1]) == 0) {
706 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
707 err_code |= ERR_ALERT | ERR_FATAL;
708 goto out;
709 }
710 global.tune.chksize = atol(args[1]);
711 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100712 else if (!strcmp(args[0], "tune.recv_enough")) {
713 if (alertif_too_many_args(1, file, linenum, args, &err_code))
714 goto out;
715 if (*(args[1]) == 0) {
716 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
717 err_code |= ERR_ALERT | ERR_FATAL;
718 goto out;
719 }
720 global.tune.recv_enough = atol(args[1]);
721 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200722#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200723 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200724 if (alertif_too_many_args(0, file, linenum, args, &err_code))
725 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200726 global.tune.sslprivatecache = 1;
727 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100728 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
730 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200731 if (*(args[1]) == 0) {
732 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
733 err_code |= ERR_ALERT | ERR_FATAL;
734 goto out;
735 }
736 global.tune.sslcachesize = atol(args[1]);
737 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100738 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
739 unsigned int ssllifetime;
740 const char *res;
741
William Lallemand1a748ae2015-05-19 16:37:23 +0200742 if (alertif_too_many_args(1, file, linenum, args, &err_code))
743 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100744 if (*(args[1]) == 0) {
745 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
746 err_code |= ERR_ALERT | ERR_FATAL;
747 goto out;
748 }
749
750 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
751 if (res) {
752 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
753 file, linenum, *res, args[0]);
754 err_code |= ERR_ALERT | ERR_FATAL;
755 goto out;
756 }
757
758 global.tune.ssllifetime = ssllifetime;
759 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100760 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200761 if (alertif_too_many_args(1, file, linenum, args, &err_code))
762 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100763 if (*(args[1]) == 0) {
764 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
765 err_code |= ERR_ALERT | ERR_FATAL;
766 goto out;
767 }
768 global.tune.ssl_max_record = atol(args[1]);
769 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200770#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200771 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200772 if (alertif_too_many_args(1, file, linenum, args, &err_code))
773 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200774 if (*(args[1]) == 0) {
775 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
776 err_code |= ERR_ALERT | ERR_FATAL;
777 goto out;
778 }
779 global.tune.ssl_default_dh_param = atol(args[1]);
780 if (global.tune.ssl_default_dh_param < 1024) {
781 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
782 err_code |= ERR_ALERT | ERR_FATAL;
783 goto out;
784 }
785 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200786#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200787 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
788 if (alertif_too_many_args(1, file, linenum, args, &err_code))
789 goto out;
790 if (*(args[1]) == 0) {
791 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
792 err_code |= ERR_ALERT | ERR_FATAL;
793 goto out;
794 }
795 global.tune.ssl_ctx_cache = atoi(args[1]);
796 if (global.tune.ssl_ctx_cache < 0) {
797 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
798 file, linenum, args[0]);
799 err_code |= ERR_ALERT | ERR_FATAL;
800 goto out;
801 }
802 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200803#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100804 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200805 if (alertif_too_many_args(1, file, linenum, args, &err_code))
806 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100807 if (*(args[1]) == 0) {
808 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
809 err_code |= ERR_ALERT | ERR_FATAL;
810 goto out;
811 }
812 global.tune.buf_limit = atol(args[1]);
813 if (global.tune.buf_limit) {
814 if (global.tune.buf_limit < 3)
815 global.tune.buf_limit = 3;
816 if (global.tune.buf_limit <= global.tune.reserved_bufs)
817 global.tune.buf_limit = global.tune.reserved_bufs + 1;
818 }
819 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100820 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200821 if (alertif_too_many_args(1, file, linenum, args, &err_code))
822 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100823 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.reserved_bufs = atol(args[1]);
829 if (global.tune.reserved_bufs < 2)
830 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100831 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
832 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100833 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200834 else if (!strcmp(args[0], "tune.bufsize")) {
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.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200843 if (global.tune.bufsize <= 0) {
844 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
845 err_code |= ERR_ALERT | ERR_FATAL;
846 goto out;
847 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100848 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100849 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200850 }
851 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200854 if (*(args[1]) == 0) {
855 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
856 err_code |= ERR_ALERT | ERR_FATAL;
857 goto out;
858 }
859 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200860 if (global.tune.maxrewrite < 0) {
861 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
862 err_code |= ERR_ALERT | ERR_FATAL;
863 goto out;
864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100866 else if (!strcmp(args[0], "tune.idletimer")) {
867 unsigned int idle;
868 const char *res;
869
William Lallemand1a748ae2015-05-19 16:37:23 +0200870 if (alertif_too_many_args(1, file, linenum, args, &err_code))
871 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100872 if (*(args[1]) == 0) {
873 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
874 err_code |= ERR_ALERT | ERR_FATAL;
875 goto out;
876 }
877
878 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
879 if (res) {
880 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
881 file, linenum, *res, args[0]);
882 err_code |= ERR_ALERT | ERR_FATAL;
883 goto out;
884 }
885
886 if (idle > 65535) {
887 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
888 err_code |= ERR_ALERT | ERR_FATAL;
889 goto out;
890 }
891 global.tune.idle_timer = idle;
892 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100893 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200894 if (alertif_too_many_args(1, file, linenum, args, &err_code))
895 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100896 if (global.tune.client_rcvbuf != 0) {
897 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
898 err_code |= ERR_ALERT;
899 goto out;
900 }
901 if (*(args[1]) == 0) {
902 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
903 err_code |= ERR_ALERT | ERR_FATAL;
904 goto out;
905 }
906 global.tune.client_rcvbuf = atol(args[1]);
907 }
908 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200909 if (alertif_too_many_args(1, file, linenum, args, &err_code))
910 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100911 if (global.tune.server_rcvbuf != 0) {
912 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
913 err_code |= ERR_ALERT;
914 goto out;
915 }
916 if (*(args[1]) == 0) {
917 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
918 err_code |= ERR_ALERT | ERR_FATAL;
919 goto out;
920 }
921 global.tune.server_rcvbuf = atol(args[1]);
922 }
923 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200924 if (alertif_too_many_args(1, file, linenum, args, &err_code))
925 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100926 if (global.tune.client_sndbuf != 0) {
927 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
928 err_code |= ERR_ALERT;
929 goto out;
930 }
931 if (*(args[1]) == 0) {
932 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
933 err_code |= ERR_ALERT | ERR_FATAL;
934 goto out;
935 }
936 global.tune.client_sndbuf = atol(args[1]);
937 }
938 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200939 if (alertif_too_many_args(1, file, linenum, args, &err_code))
940 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100941 if (global.tune.server_sndbuf != 0) {
942 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
943 err_code |= ERR_ALERT;
944 goto out;
945 }
946 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.server_sndbuf = atol(args[1]);
952 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200953 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200954 if (alertif_too_many_args(1, file, linenum, args, &err_code))
955 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +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.pipesize = atol(args[1]);
962 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100963 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200964 if (alertif_too_many_args(1, file, linenum, args, &err_code))
965 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100966 if (*(args[1]) == 0) {
967 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
968 err_code |= ERR_ALERT | ERR_FATAL;
969 goto out;
970 }
971 global.tune.cookie_len = atol(args[1]) + 1;
972 }
Willy Tarreauac1932d2011-10-24 19:14:41 +0200973 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200974 if (alertif_too_many_args(1, file, linenum, args, &err_code))
975 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +0200976 if (*(args[1]) == 0) {
977 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
978 err_code |= ERR_ALERT | ERR_FATAL;
979 goto out;
980 }
981 global.tune.max_http_hdr = atol(args[1]);
982 }
William Lallemanda509e4c2012-11-07 16:54:34 +0100983 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
984#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
986 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +0100987 if (*args[1]) {
988 global.tune.zlibmemlevel = atoi(args[1]);
989 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
990 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
991 file, linenum, args[0]);
992 err_code |= ERR_ALERT | ERR_FATAL;
993 goto out;
994 }
995 } else {
996 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
997 file, linenum, args[0]);
998 err_code |= ERR_ALERT | ERR_FATAL;
999 goto out;
1000 }
1001#else
1002 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1003 err_code |= ERR_ALERT | ERR_FATAL;
1004 goto out;
1005#endif
1006 }
1007 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1008#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001009 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1010 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001011 if (*args[1]) {
1012 global.tune.zlibwindowsize = atoi(args[1]);
1013 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1014 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1015 file, linenum, args[0]);
1016 err_code |= ERR_ALERT | ERR_FATAL;
1017 goto out;
1018 }
1019 } else {
1020 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1021 file, linenum, args[0]);
1022 err_code |= ERR_ALERT | ERR_FATAL;
1023 goto out;
1024 }
1025#else
1026 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1027 err_code |= ERR_ALERT | ERR_FATAL;
1028 goto out;
1029#endif
1030 }
William Lallemandf3747832012-11-09 12:33:10 +01001031 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001032 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1033 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001034 if (*args[1]) {
1035 global.tune.comp_maxlevel = atoi(args[1]);
1036 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1037 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1038 file, linenum, args[0]);
1039 err_code |= ERR_ALERT | ERR_FATAL;
1040 goto out;
1041 }
1042 } else {
1043 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1044 file, linenum, args[0]);
1045 err_code |= ERR_ALERT | ERR_FATAL;
1046 goto out;
1047 }
1048 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001049 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1050 if (*args[1]) {
1051 global.tune.pattern_cache = atoi(args[1]);
1052 if (global.tune.pattern_cache < 0) {
1053 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1054 file, linenum, args[0]);
1055 err_code |= ERR_ALERT | ERR_FATAL;
1056 goto out;
1057 }
1058 } else {
1059 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1060 file, linenum, args[0]);
1061 err_code |= ERR_ALERT | ERR_FATAL;
1062 goto out;
1063 }
1064 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001065 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001066 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1067 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001068 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001069 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001070 err_code |= ERR_ALERT;
1071 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001072 }
1073 if (*(args[1]) == 0) {
1074 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001075 err_code |= ERR_ALERT | ERR_FATAL;
1076 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001077 }
1078 global.uid = atol(args[1]);
1079 }
1080 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001081 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001083 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001084 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001085 err_code |= ERR_ALERT;
1086 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001087 }
1088 if (*(args[1]) == 0) {
1089 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT | ERR_FATAL;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 global.gid = atol(args[1]);
1094 }
Simon Horman98637e52014-06-20 12:30:16 +09001095 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001096 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1097 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001098 global.external_check = 1;
1099 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 /* user/group name handling */
1101 else if (!strcmp(args[0], "user")) {
1102 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001103 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1104 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001105 if (global.uid != 0) {
1106 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001107 err_code |= ERR_ALERT;
1108 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 }
1110 errno = 0;
1111 ha_user = getpwnam(args[1]);
1112 if (ha_user != NULL) {
1113 global.uid = (int)ha_user->pw_uid;
1114 }
1115 else {
1116 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 +02001117 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 }
1120 else if (!strcmp(args[0], "group")) {
1121 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001122 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1123 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001124 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001125 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT;
1127 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001128 }
1129 errno = 0;
1130 ha_group = getgrnam(args[1]);
1131 if (ha_group != NULL) {
1132 global.gid = (int)ha_group->gr_gid;
1133 }
1134 else {
1135 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 +02001136 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001137 }
1138 }
1139 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001140 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001141 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1142 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001143 if (*(args[1]) == 0) {
1144 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
1146 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001147 }
1148 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001149 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1150 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1151 file, linenum, args[0], LONGBITS, global.nbproc);
1152 err_code |= ERR_ALERT | ERR_FATAL;
1153 goto out;
1154 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001155 }
1156 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001157 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1158 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001159 if (global.maxconn != 0) {
1160 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001161 err_code |= ERR_ALERT;
1162 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001163 }
1164 if (*(args[1]) == 0) {
1165 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT | ERR_FATAL;
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 }
1169 global.maxconn = atol(args[1]);
1170#ifdef SYSTEM_MAXCONN
1171 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1172 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);
1173 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001174 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001175 }
1176#endif /* SYSTEM_MAXCONN */
1177 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001178 else if (!strcmp(args[0], "maxsslconn")) {
1179#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001180 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1181 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001182 if (*(args[1]) == 0) {
1183 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1184 err_code |= ERR_ALERT | ERR_FATAL;
1185 goto out;
1186 }
1187 global.maxsslconn = atol(args[1]);
1188#else
Emeric Brun0914df82012-10-02 18:45:42 +02001189 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1190 err_code |= ERR_ALERT | ERR_FATAL;
1191 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001192#endif
1193 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001194 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1195#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001196 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1197 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001198 if (*(args[1]) == 0) {
1199 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1200 err_code |= ERR_ALERT | ERR_FATAL;
1201 goto out;
1202 }
1203 free(global.listen_default_ciphers);
1204 global.listen_default_ciphers = strdup(args[1]);
1205#else
1206 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1207 err_code |= ERR_ALERT | ERR_FATAL;
1208 goto out;
1209#endif
1210 }
1211 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1212#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1214 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001215 if (*(args[1]) == 0) {
1216 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1217 err_code |= ERR_ALERT | ERR_FATAL;
1218 goto out;
1219 }
1220 free(global.connect_default_ciphers);
1221 global.connect_default_ciphers = strdup(args[1]);
1222#else
1223 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226#endif
1227 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001228#ifdef USE_OPENSSL
1229#ifndef OPENSSL_NO_DH
1230 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1231 if (*(args[1]) == 0) {
1232 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235 }
1236 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1237 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1238 err_code |= ERR_ALERT | ERR_FATAL;
1239 goto out;
1240 }
1241 }
1242#endif
1243#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001244 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001245 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1246 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001247 if (*(args[1]) == 0) {
1248 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1249 err_code |= ERR_ALERT | ERR_FATAL;
1250 goto out;
1251 }
1252 if (strcmp(args[1],"none") == 0)
1253 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1254 else if (strcmp(args[1],"required") == 0)
1255 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1256 else {
1257 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001262 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001263 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1264 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001265 if (global.cps_lim != 0) {
1266 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT;
1268 goto out;
1269 }
1270 if (*(args[1]) == 0) {
1271 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1272 err_code |= ERR_ALERT | ERR_FATAL;
1273 goto out;
1274 }
1275 global.cps_lim = atol(args[1]);
1276 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001277 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001278 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1279 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001280 if (global.sps_lim != 0) {
1281 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1282 err_code |= ERR_ALERT;
1283 goto out;
1284 }
1285 if (*(args[1]) == 0) {
1286 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1287 err_code |= ERR_ALERT | ERR_FATAL;
1288 goto out;
1289 }
1290 global.sps_lim = atol(args[1]);
1291 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001292 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001293 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1294 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001295 if (global.ssl_lim != 0) {
1296 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1297 err_code |= ERR_ALERT;
1298 goto out;
1299 }
1300 if (*(args[1]) == 0) {
1301 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1302 err_code |= ERR_ALERT | ERR_FATAL;
1303 goto out;
1304 }
1305 global.ssl_lim = atol(args[1]);
1306 }
William Lallemandd85f9172012-11-09 17:05:39 +01001307 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001308 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1309 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001310 if (*(args[1]) == 0) {
1311 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 global.comp_rate_lim = atoi(args[1]) * 1024;
1316 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001317 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001318 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1319 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001320 if (global.maxpipes != 0) {
1321 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001322 err_code |= ERR_ALERT;
1323 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001324 }
1325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001329 }
1330 global.maxpipes = atol(args[1]);
1331 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001332 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001333 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1334 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001335 if (*(args[1]) == 0) {
1336 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1337 err_code |= ERR_ALERT | ERR_FATAL;
1338 goto out;
1339 }
William Lallemande3a7d992012-11-20 11:25:20 +01001340 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001341 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001342 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001343 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1344 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001345 if (*(args[1]) == 0) {
1346 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1347 err_code |= ERR_ALERT | ERR_FATAL;
1348 goto out;
1349 }
1350 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001351 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001352 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1353 err_code |= ERR_ALERT | ERR_FATAL;
1354 goto out;
1355 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001356 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001357
Willy Tarreaubaaee002006-06-26 02:48:02 +02001358 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001359 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1360 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001361 if (global.rlimit_nofile != 0) {
1362 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001363 err_code |= ERR_ALERT;
1364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001365 }
1366 if (*(args[1]) == 0) {
1367 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001368 err_code |= ERR_ALERT | ERR_FATAL;
1369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 }
1371 global.rlimit_nofile = atol(args[1]);
1372 }
1373 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001374 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1375 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001376 if (global.chroot != NULL) {
1377 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001378 err_code |= ERR_ALERT;
1379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001380 }
1381 if (*(args[1]) == 0) {
1382 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001383 err_code |= ERR_ALERT | ERR_FATAL;
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 }
1386 global.chroot = strdup(args[1]);
1387 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001388 else if (!strcmp(args[0], "description")) {
1389 int i, len=0;
1390 char *d;
1391
1392 if (!*args[1]) {
1393 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1394 file, linenum, args[0]);
1395 err_code |= ERR_ALERT | ERR_FATAL;
1396 goto out;
1397 }
1398
Willy Tarreau348acfe2014-04-14 15:00:39 +02001399 for (i = 1; *args[i]; i++)
1400 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001401
1402 if (global.desc)
1403 free(global.desc);
1404
1405 global.desc = d = (char *)calloc(1, len);
1406
Willy Tarreau348acfe2014-04-14 15:00:39 +02001407 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1408 for (i = 2; *args[i]; i++)
1409 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410 }
1411 else if (!strcmp(args[0], "node")) {
1412 int i;
1413 char c;
1414
William Lallemand1a748ae2015-05-19 16:37:23 +02001415 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1416 goto out;
1417
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001418 for (i=0; args[1][i]; i++) {
1419 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001420 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1421 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001422 break;
1423 }
1424
1425 if (!i || args[1][i]) {
1426 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1427 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1428 file, linenum, args[0]);
1429 err_code |= ERR_ALERT | ERR_FATAL;
1430 goto out;
1431 }
1432
1433 if (global.node)
1434 free(global.node);
1435
1436 global.node = strdup(args[1]);
1437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001438 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001439 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001441 if (global.pidfile != NULL) {
1442 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001443 err_code |= ERR_ALERT;
1444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001445 }
1446 if (*(args[1]) == 0) {
1447 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001448 err_code |= ERR_ALERT | ERR_FATAL;
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 }
1451 global.pidfile = strdup(args[1]);
1452 }
Emeric Bruned760922010-10-22 17:59:25 +02001453 else if (!strcmp(args[0], "unix-bind")) {
1454 int cur_arg = 1;
1455 while (*(args[cur_arg])) {
1456 if (!strcmp(args[cur_arg], "prefix")) {
1457 if (global.unix_bind.prefix != NULL) {
1458 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1459 err_code |= ERR_ALERT;
1460 cur_arg += 2;
1461 continue;
1462 }
1463
1464 if (*(args[cur_arg+1]) == 0) {
1465 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1466 err_code |= ERR_ALERT | ERR_FATAL;
1467 goto out;
1468 }
1469 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1470 cur_arg += 2;
1471 continue;
1472 }
1473
1474 if (!strcmp(args[cur_arg], "mode")) {
1475
1476 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1477 cur_arg += 2;
1478 continue;
1479 }
1480
1481 if (!strcmp(args[cur_arg], "uid")) {
1482
1483 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1484 cur_arg += 2;
1485 continue;
1486 }
1487
1488 if (!strcmp(args[cur_arg], "gid")) {
1489
1490 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1491 cur_arg += 2;
1492 continue;
1493 }
1494
1495 if (!strcmp(args[cur_arg], "user")) {
1496 struct passwd *user;
1497
1498 user = getpwnam(args[cur_arg + 1]);
1499 if (!user) {
1500 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1501 file, linenum, args[0], args[cur_arg + 1 ]);
1502 err_code |= ERR_ALERT | ERR_FATAL;
1503 goto out;
1504 }
1505
1506 global.unix_bind.ux.uid = user->pw_uid;
1507 cur_arg += 2;
1508 continue;
1509 }
1510
1511 if (!strcmp(args[cur_arg], "group")) {
1512 struct group *group;
1513
1514 group = getgrnam(args[cur_arg + 1]);
1515 if (!group) {
1516 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1517 file, linenum, args[0], args[cur_arg + 1 ]);
1518 err_code |= ERR_ALERT | ERR_FATAL;
1519 goto out;
1520 }
1521
1522 global.unix_bind.ux.gid = group->gr_gid;
1523 cur_arg += 2;
1524 continue;
1525 }
1526
Willy Tarreaub48f9582011-09-05 01:17:06 +02001527 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001528 file, linenum, args[0]);
1529 err_code |= ERR_ALERT | ERR_FATAL;
1530 goto out;
1531 }
1532 }
William Lallemand0f99e342011-10-12 17:50:54 +02001533 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1534 /* delete previous herited or defined syslog servers */
1535 struct logsrv *back;
1536 struct logsrv *tmp;
1537
1538 if (*(args[1]) != 0) {
1539 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1540 err_code |= ERR_ALERT | ERR_FATAL;
1541 goto out;
1542 }
1543
1544 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1545 LIST_DEL(&tmp->list);
1546 free(tmp);
1547 }
1548 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001549 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001550 struct sockaddr_storage *sk;
1551 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001552 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001553 int arg = 0;
1554 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001555
William Lallemand1a748ae2015-05-19 16:37:23 +02001556 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1557 goto out;
1558
Willy Tarreaubaaee002006-06-26 02:48:02 +02001559 if (*(args[1]) == 0 || *(args[2]) == 0) {
1560 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001561 err_code |= ERR_ALERT | ERR_FATAL;
1562 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001563 }
William Lallemand0f99e342011-10-12 17:50:54 +02001564
1565 logsrv = calloc(1, sizeof(struct logsrv));
1566
Willy Tarreau18324f52014-06-27 18:10:07 +02001567 /* just after the address, a length may be specified */
1568 if (strcmp(args[arg+2], "len") == 0) {
1569 len = atoi(args[arg+3]);
1570 if (len < 80 || len > 65535) {
1571 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1572 file, linenum, args[arg+3]);
1573 err_code |= ERR_ALERT | ERR_FATAL;
1574 goto out;
1575 }
1576 logsrv->maxlen = len;
1577
1578 /* skip these two args */
1579 arg += 2;
1580 }
1581 else
1582 logsrv->maxlen = MAX_SYSLOG_LEN;
1583
1584 if (logsrv->maxlen > global.max_syslog_len) {
1585 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02001586 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02001587 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001588 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02001589 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001590 }
1591
Dragan Dosen1322d092015-09-22 16:05:32 +02001592 /* after the length, a format may be specified */
1593 if (strcmp(args[arg+2], "format") == 0) {
1594 logsrv->format = get_log_format(args[arg+3]);
1595 if (logsrv->format < 0) {
1596 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1597 err_code |= ERR_ALERT | ERR_FATAL;
1598 goto out;
1599 }
1600
1601 /* skip these two args */
1602 arg += 2;
1603 }
1604
William Lallemand1a748ae2015-05-19 16:37:23 +02001605 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
1606 goto out;
1607
Willy Tarreau18324f52014-06-27 18:10:07 +02001608 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001609 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001610 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001611 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001612 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001613 }
1614
William Lallemand0f99e342011-10-12 17:50:54 +02001615 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001616 if (*(args[arg+3])) {
1617 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001618 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001619 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001620 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001621 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001622 }
1623 }
1624
William Lallemand0f99e342011-10-12 17:50:54 +02001625 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001626 if (*(args[arg+4])) {
1627 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001628 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001629 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001630 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001631 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001632 }
1633 }
1634
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001635 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001636 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001637 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001638 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001639 free(logsrv);
1640 goto out;
1641 }
1642 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001643
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001644 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001645 if (port1 != port2) {
1646 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1647 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001648 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001649 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001650 goto out;
1651 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001652
William Lallemand0f99e342011-10-12 17:50:54 +02001653 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001654 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001655 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001656 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001657
William Lallemand0f99e342011-10-12 17:50:54 +02001658 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001659 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001660 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1661 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001662
1663 if (global.log_send_hostname != NULL) {
1664 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1665 err_code |= ERR_ALERT;
1666 goto out;
1667 }
1668
1669 if (*(args[1]))
1670 name = args[1];
1671 else
1672 name = hostname;
1673
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001674 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001675 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001676 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001677 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1678 if (global.server_state_base != NULL) {
1679 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1680 err_code |= ERR_ALERT;
1681 goto out;
1682 }
1683
1684 if (!*(args[1])) {
1685 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1686 err_code |= ERR_FATAL;
1687 goto out;
1688 }
1689
1690 global.server_state_base = strdup(args[1]);
1691 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001692 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1693 if (global.server_state_file != NULL) {
1694 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1695 err_code |= ERR_ALERT;
1696 goto out;
1697 }
1698
1699 if (!*(args[1])) {
1700 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1701 err_code |= ERR_FATAL;
1702 goto out;
1703 }
1704
1705 global.server_state_file = strdup(args[1]);
1706 }
Kevinm48936af2010-12-22 16:08:21 +00001707 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001708 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1709 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001710 if (*(args[1]) == 0) {
1711 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1712 err_code |= ERR_ALERT | ERR_FATAL;
1713 goto out;
1714 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001715 chunk_destroy(&global.log_tag);
1716 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001717 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001718 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1720 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001721 if (global.spread_checks != 0) {
1722 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001723 err_code |= ERR_ALERT;
1724 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001725 }
1726 if (*(args[1]) == 0) {
1727 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001728 err_code |= ERR_ALERT | ERR_FATAL;
1729 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001730 }
1731 global.spread_checks = atol(args[1]);
1732 if (global.spread_checks < 0 || global.spread_checks > 50) {
1733 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001734 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001735 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001736 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001737 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1738 const char *err;
1739 unsigned int val;
1740
William Lallemand1a748ae2015-05-19 16:37:23 +02001741 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1742 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001743 if (*(args[1]) == 0) {
1744 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1745 err_code |= ERR_ALERT | ERR_FATAL;
1746 goto out;
1747 }
1748
1749 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1750 if (err) {
1751 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1752 err_code |= ERR_ALERT | ERR_FATAL;
1753 }
1754 global.max_spread_checks = val;
1755 if (global.max_spread_checks < 0) {
1756 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 }
1759 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001760 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1761#ifdef USE_CPU_AFFINITY
1762 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001763 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001764 unsigned long cpus = 0;
1765
1766 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001767 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001768 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001769 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001770 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001771 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001772 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001773 proc = atol(args[1]);
1774 if (proc >= 1 && proc <= LONGBITS)
1775 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001776 }
1777
1778 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001779 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",
1780 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001781 err_code |= ERR_ALERT | ERR_FATAL;
1782 goto out;
1783 }
1784
1785 cur_arg = 2;
1786 while (*args[cur_arg]) {
1787 unsigned int low, high;
1788
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001789 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001790 char *dash = strchr(args[cur_arg], '-');
1791
1792 low = high = str2uic(args[cur_arg]);
1793 if (dash)
1794 high = str2uic(dash + 1);
1795
1796 if (high < low) {
1797 unsigned int swap = low;
1798 low = high;
1799 high = swap;
1800 }
1801
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001802 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001803 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001804 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001805 err_code |= ERR_ALERT | ERR_FATAL;
1806 goto out;
1807 }
1808
1809 while (low <= high)
1810 cpus |= 1UL << low++;
1811 }
1812 else {
1813 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1814 file, linenum, args[0], args[cur_arg]);
1815 err_code |= ERR_ALERT | ERR_FATAL;
1816 goto out;
1817 }
1818 cur_arg++;
1819 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001820 for (i = 0; i < LONGBITS; i++)
1821 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001822 global.cpu_map[i] = cpus;
1823#else
1824 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1825 err_code |= ERR_ALERT | ERR_FATAL;
1826 goto out;
1827#endif
1828 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001829 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1830 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1831 goto out;
1832
1833 if (*(args[2]) == 0) {
1834 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1835 err_code |= ERR_ALERT | ERR_FATAL;
1836 goto out;
1837 }
1838
1839 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1840 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1841 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1842 err_code |= ERR_ALERT | ERR_FATAL;
1843 goto out;
1844 }
1845 }
1846 else if (!strcmp(args[0], "unsetenv")) {
1847 int arg;
1848
1849 if (*(args[1]) == 0) {
1850 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1851 err_code |= ERR_ALERT | ERR_FATAL;
1852 goto out;
1853 }
1854
1855 for (arg = 1; *args[arg]; arg++) {
1856 if (unsetenv(args[arg]) != 0) {
1857 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 }
1862 }
1863 else if (!strcmp(args[0], "resetenv")) {
1864 extern char **environ;
1865 char **env = environ;
1866
1867 /* args contain variable names to keep, one per argument */
1868 while (*env) {
1869 int arg;
1870
1871 /* look for current variable in among all those we want to keep */
1872 for (arg = 1; *args[arg]; arg++) {
1873 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1874 (*env)[strlen(args[arg])] == '=')
1875 break;
1876 }
1877
1878 /* delete this variable */
1879 if (!*args[arg]) {
1880 char *delim = strchr(*env, '=');
1881
1882 if (!delim || delim - *env >= trash.size) {
1883 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1884 err_code |= ERR_ALERT | ERR_FATAL;
1885 goto out;
1886 }
1887
1888 memcpy(trash.str, *env, delim - *env);
1889 trash.str[delim - *env] = 0;
1890
1891 if (unsetenv(trash.str) != 0) {
1892 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1893 err_code |= ERR_ALERT | ERR_FATAL;
1894 goto out;
1895 }
1896 }
1897 else
1898 env++;
1899 }
1900 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001901 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001902 struct cfg_kw_list *kwl;
1903 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001904 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001905
1906 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1907 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1908 if (kwl->kw[index].section != CFG_GLOBAL)
1909 continue;
1910 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001911 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001912 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001913 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001914 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001915 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001916 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001917 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001918 err_code |= ERR_WARN;
1919 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001920 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001921 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001922 }
1923 }
1924 }
1925
Willy Tarreaubaaee002006-06-26 02:48:02 +02001926 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001927 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001928 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001929
Willy Tarreau058e9072009-07-20 09:30:05 +02001930 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001931 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001932 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001933}
1934
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001935void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001936{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001937 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 defproxy.mode = PR_MODE_TCP;
1939 defproxy.state = PR_STNEW;
1940 defproxy.maxconn = cfg_maxpconn;
1941 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001942 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001943
Simon Horman66183002013-02-23 10:16:43 +09001944 defproxy.defsrv.check.inter = DEF_CHKINTR;
1945 defproxy.defsrv.check.fastinter = 0;
1946 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001947 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1948 defproxy.defsrv.agent.fastinter = 0;
1949 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001950 defproxy.defsrv.check.rise = DEF_RISETIME;
1951 defproxy.defsrv.check.fall = DEF_FALLTIME;
1952 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1953 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001954 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001955 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001956 defproxy.defsrv.maxqueue = 0;
1957 defproxy.defsrv.minconn = 0;
1958 defproxy.defsrv.maxconn = 0;
1959 defproxy.defsrv.slowstart = 0;
1960 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1961 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1962 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001963
1964 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001965 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001966}
1967
Willy Tarreauade5ec42010-01-28 19:33:49 +01001968
Willy Tarreau63af98d2014-05-18 08:11:41 +02001969/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1970 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1971 * ERR_FATAL in case of error.
1972 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001973static int create_cond_regex_rule(const char *file, int line,
1974 struct proxy *px, int dir, int action, int flags,
1975 const char *cmd, const char *reg, const char *repl,
1976 const char **cond_start)
1977{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001978 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001979 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001980 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001981 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001982 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001983 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001984 int cs;
1985 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001986
1987 if (px == &defproxy) {
1988 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001989 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001990 goto err;
1991 }
1992
1993 if (*reg == 0) {
1994 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02001995 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001996 goto err;
1997 }
1998
1999 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002000 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002001
Willy Tarreau5321c422010-01-28 20:35:13 +01002002 if (cond_start &&
2003 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002004 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2005 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2006 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002007 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002008 goto err;
2009 }
2010 }
2011 else if (cond_start && **cond_start) {
2012 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2013 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002014 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002015 goto err;
2016 }
2017
Willy Tarreau63af98d2014-05-18 08:11:41 +02002018 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002019 (dir == SMP_OPT_DIR_REQ) ?
2020 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2021 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2022 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002023
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002024 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002025 if (!preg) {
2026 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002027 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002028 goto err;
2029 }
2030
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002031 cs = !(flags & REG_ICASE);
2032 cap = !(flags & REG_NOSUB);
2033 error = NULL;
2034 if (!regex_comp(reg, preg, cs, cap, &error)) {
2035 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2036 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002037 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002038 goto err;
2039 }
2040
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002041 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002042 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002043 if (repl && err) {
2044 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2045 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002046 ret_code |= ERR_ALERT | ERR_FATAL;
2047 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002048 }
2049
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002050 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002051 ret_code |= ERR_WARN;
2052
2053 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002054
Willy Tarreau63af98d2014-05-18 08:11:41 +02002055 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002056 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002057 err:
2058 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002059 free(errmsg);
2060 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002061}
2062
Willy Tarreaubaaee002006-06-26 02:48:02 +02002063/*
William Lallemand51097192015-04-14 16:35:22 +02002064 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002065 * Returns the error code, 0 if OK, or any combination of :
2066 * - ERR_ABORT: must abort ASAP
2067 * - ERR_FATAL: we can continue parsing but not start the service
2068 * - ERR_WARN: a warning has been emitted
2069 * - ERR_ALERT: an alert has been emitted
2070 * Only the two first ones can stop processing, the two others are just
2071 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002072 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002073int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2074{
2075 static struct peers *curpeers = NULL;
2076 struct peer *newpeer = NULL;
2077 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002078 struct bind_conf *bind_conf;
2079 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002080 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002081 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002082
2083 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002084 if (!*args[1]) {
2085 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002086 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002087 goto out;
2088 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002089
William Lallemand6e62fb62015-04-28 16:55:23 +02002090 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2091 goto out;
2092
Emeric Brun32da3c42010-09-23 18:39:19 +02002093 err = invalid_char(args[1]);
2094 if (err) {
2095 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2096 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002097 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002098 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002099 }
2100
2101 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2102 /*
2103 * If there are two proxies with the same name only following
2104 * combinations are allowed:
2105 */
2106 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002107 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 +02002108 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002109 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002110 }
2111 }
2112
2113 if ((curpeers = (struct peers *)calloc(1, sizeof(struct peers))) == NULL) {
2114 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2115 err_code |= ERR_ALERT | ERR_ABORT;
2116 goto out;
2117 }
2118
2119 curpeers->next = peers;
2120 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002121 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002122 curpeers->conf.line = linenum;
2123 curpeers->last_change = now.tv_sec;
2124 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002125 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002126 }
2127 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002128 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002129 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002130 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002131
2132 if (!*args[2]) {
2133 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2134 file, linenum, args[0]);
2135 err_code |= ERR_ALERT | ERR_FATAL;
2136 goto out;
2137 }
2138
2139 err = invalid_char(args[1]);
2140 if (err) {
2141 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2142 file, linenum, *err, args[1]);
2143 err_code |= ERR_ALERT | ERR_FATAL;
2144 goto out;
2145 }
2146
2147 if ((newpeer = (struct peer *)calloc(1, sizeof(struct peer))) == NULL) {
2148 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2149 err_code |= ERR_ALERT | ERR_ABORT;
2150 goto out;
2151 }
2152
2153 /* the peers are linked backwards first */
2154 curpeers->count++;
2155 newpeer->next = curpeers->remote;
2156 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002157 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 newpeer->conf.line = linenum;
2159
2160 newpeer->last_change = now.tv_sec;
2161 newpeer->id = strdup(args[1]);
2162
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002163 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002164 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002165 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002166 err_code |= ERR_ALERT | ERR_FATAL;
2167 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002168 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002169
2170 proto = protocol_by_family(sk->ss_family);
2171 if (!proto || !proto->connect) {
2172 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2173 file, linenum, args[0], args[1]);
2174 err_code |= ERR_ALERT | ERR_FATAL;
2175 goto out;
2176 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002177
2178 if (port1 != port2) {
2179 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2180 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002181 err_code |= ERR_ALERT | ERR_FATAL;
2182 goto out;
2183 }
2184
Willy Tarreau2aa38802013-02-20 19:20:59 +01002185 if (!port1) {
2186 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2187 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002188 err_code |= ERR_ALERT | ERR_FATAL;
2189 goto out;
2190 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002191
Emeric Brun32da3c42010-09-23 18:39:19 +02002192 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002193 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002194 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002195 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002196
Emeric Brun32da3c42010-09-23 18:39:19 +02002197 if (strcmp(newpeer->id, localpeer) == 0) {
2198 /* Current is local peer, it define a frontend */
2199 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002200 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002201
2202 if (!curpeers->peers_fe) {
2203 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2204 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2205 err_code |= ERR_ALERT | ERR_ABORT;
2206 goto out;
2207 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002208
Willy Tarreau237250c2011-07-29 01:49:03 +02002209 init_new_proxy(curpeers->peers_fe);
2210 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002211 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002212 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2213 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002214 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002215
2216 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2217
Willy Tarreau902636f2013-03-10 19:44:48 +01002218 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2219 if (errmsg && *errmsg) {
2220 indent_msg(&errmsg, 2);
2221 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002222 }
2223 else
2224 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2225 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002226 err_code |= ERR_FATAL;
2227 goto out;
2228 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002229
2230 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002231 l->maxaccept = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002232 l->maxconn = ((struct proxy *)curpeers->peers_fe)->maxconn;
2233 l->backlog = ((struct proxy *)curpeers->peers_fe)->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002234 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002235 l->handler = process_stream;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002236 l->analysers |= ((struct proxy *)curpeers->peers_fe)->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01002237 l->default_target = ((struct proxy *)curpeers->peers_fe)->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002238 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2239 global.maxsock += l->maxconn;
2240 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002241 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002242 else {
2243 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2244 file, linenum, args[0], args[1],
2245 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2246 err_code |= ERR_FATAL;
2247 goto out;
2248 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002249 }
2250 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002251 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2252 curpeers->state = PR_STSTOPPED;
2253 }
2254 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2255 curpeers->state = PR_STNEW;
2256 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002257 else if (*args[0] != 0) {
2258 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2259 err_code |= ERR_ALERT | ERR_FATAL;
2260 goto out;
2261 }
2262
2263out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002264 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002265 return err_code;
2266}
2267
Baptiste Assmann325137d2015-04-13 23:40:55 +02002268/*
2269 * Parse a <resolvers> section.
2270 * Returns the error code, 0 if OK, or any combination of :
2271 * - ERR_ABORT: must abort ASAP
2272 * - ERR_FATAL: we can continue parsing but not start the service
2273 * - ERR_WARN: a warning has been emitted
2274 * - ERR_ALERT: an alert has been emitted
2275 * Only the two first ones can stop processing, the two others are just
2276 * indicators.
2277 */
2278int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2279{
2280 static struct dns_resolvers *curr_resolvers = NULL;
2281 struct dns_nameserver *newnameserver = NULL;
2282 const char *err;
2283 int err_code = 0;
2284 char *errmsg = NULL;
2285
2286 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2287 if (!*args[1]) {
2288 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2289 err_code |= ERR_ALERT | ERR_ABORT;
2290 goto out;
2291 }
2292
2293 err = invalid_char(args[1]);
2294 if (err) {
2295 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2296 file, linenum, *err, args[0], args[1]);
2297 err_code |= ERR_ALERT | ERR_ABORT;
2298 goto out;
2299 }
2300
2301 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2302 /* Error if two resolvers owns the same name */
2303 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2304 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2305 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2306 err_code |= ERR_ALERT | ERR_ABORT;
2307 }
2308 }
2309
2310 if ((curr_resolvers = (struct dns_resolvers *)calloc(1, sizeof(struct dns_resolvers))) == NULL) {
2311 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2312 err_code |= ERR_ALERT | ERR_ABORT;
2313 goto out;
2314 }
2315
2316 /* default values */
2317 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2318 curr_resolvers->conf.file = strdup(file);
2319 curr_resolvers->conf.line = linenum;
2320 curr_resolvers->id = strdup(args[1]);
2321 curr_resolvers->query_ids = EB_ROOT;
2322 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002323 curr_resolvers->hold.valid = 10000;
2324 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002325 curr_resolvers->resolve_retries = 3;
2326 LIST_INIT(&curr_resolvers->nameserver_list);
2327 LIST_INIT(&curr_resolvers->curr_resolution);
2328 }
2329 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2330 struct sockaddr_storage *sk;
2331 int port1, port2;
2332 struct protocol *proto;
2333
2334 if (!*args[2]) {
2335 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2336 file, linenum, args[0]);
2337 err_code |= ERR_ALERT | ERR_FATAL;
2338 goto out;
2339 }
2340
2341 err = invalid_char(args[1]);
2342 if (err) {
2343 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2344 file, linenum, *err, args[1]);
2345 err_code |= ERR_ALERT | ERR_FATAL;
2346 goto out;
2347 }
2348
Baptiste Assmanna315c552015-11-02 22:55:49 +01002349 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2350 /* Error if two resolvers owns the same name */
2351 if (strcmp(newnameserver->id, args[1]) == 0) {
2352 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2353 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2354 err_code |= ERR_ALERT | ERR_FATAL;
2355 }
2356 }
2357
Baptiste Assmann325137d2015-04-13 23:40:55 +02002358 if ((newnameserver = (struct dns_nameserver *)calloc(1, sizeof(struct dns_nameserver))) == NULL) {
2359 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2360 err_code |= ERR_ALERT | ERR_ABORT;
2361 goto out;
2362 }
2363
2364 /* the nameservers are linked backward first */
2365 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2366 curr_resolvers->count_nameservers++;
2367 newnameserver->resolvers = curr_resolvers;
2368 newnameserver->conf.file = strdup(file);
2369 newnameserver->conf.line = linenum;
2370 newnameserver->id = strdup(args[1]);
2371
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002372 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002373 if (!sk) {
2374 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2375 err_code |= ERR_ALERT | ERR_FATAL;
2376 goto out;
2377 }
2378
2379 proto = protocol_by_family(sk->ss_family);
2380 if (!proto || !proto->connect) {
2381 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2382 file, linenum, args[0], args[1]);
2383 err_code |= ERR_ALERT | ERR_FATAL;
2384 goto out;
2385 }
2386
2387 if (port1 != port2) {
2388 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2389 file, linenum, args[0], args[1], args[2]);
2390 err_code |= ERR_ALERT | ERR_FATAL;
2391 goto out;
2392 }
2393
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002394 if (!port1 && !port2) {
2395 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2396 file, linenum, args[0], args[1]);
2397 err_code |= ERR_ALERT | ERR_FATAL;
2398 goto out;
2399 }
2400
Baptiste Assmann325137d2015-04-13 23:40:55 +02002401 newnameserver->addr = *sk;
2402 }
2403 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2404 const char *res;
2405 unsigned int time;
2406
2407 if (!*args[2]) {
2408 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2409 file, linenum, args[0]);
2410 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2411 err_code |= ERR_ALERT | ERR_FATAL;
2412 goto out;
2413 }
2414 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2415 if (res) {
2416 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2417 file, linenum, *res, args[0]);
2418 err_code |= ERR_ALERT | ERR_FATAL;
2419 goto out;
2420 }
2421 if (strcmp(args[1], "valid") == 0)
2422 curr_resolvers->hold.valid = time;
2423 else {
2424 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2425 file, linenum, args[0], args[1]);
2426 err_code |= ERR_ALERT | ERR_FATAL;
2427 goto out;
2428 }
2429
2430 }
2431 else if (strcmp(args[0], "resolve_retries") == 0) {
2432 if (!*args[1]) {
2433 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2434 file, linenum, args[0]);
2435 err_code |= ERR_ALERT | ERR_FATAL;
2436 goto out;
2437 }
2438 curr_resolvers->resolve_retries = atoi(args[1]);
2439 }
2440 else if (strcmp(args[0], "timeout") == 0) {
2441 const char *res;
2442 unsigned int timeout_retry;
2443
2444 if (!*args[2]) {
2445 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2451 if (res) {
2452 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2453 file, linenum, *res, args[0]);
2454 err_code |= ERR_ALERT | ERR_FATAL;
2455 goto out;
2456 }
2457 curr_resolvers->timeout.retry = timeout_retry;
2458 } /* neither "nameserver" nor "resolvers" */
2459 else if (*args[0] != 0) {
2460 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2461 err_code |= ERR_ALERT | ERR_FATAL;
2462 goto out;
2463 }
2464
2465 out:
2466 free(errmsg);
2467 return err_code;
2468}
Simon Horman0d16a402015-01-30 11:22:58 +09002469
2470/*
William Lallemand51097192015-04-14 16:35:22 +02002471 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002472 * Returns the error code, 0 if OK, or any combination of :
2473 * - ERR_ABORT: must abort ASAP
2474 * - ERR_FATAL: we can continue parsing but not start the service
2475 * - ERR_WARN: a warning has been emitted
2476 * - ERR_ALERT: an alert has been emitted
2477 * Only the two first ones can stop processing, the two others are just
2478 * indicators.
2479 */
2480int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2481{
2482 static struct mailers *curmailers = NULL;
2483 struct mailer *newmailer = NULL;
2484 const char *err;
2485 int err_code = 0;
2486 char *errmsg = NULL;
2487
2488 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2489 if (!*args[1]) {
2490 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2491 err_code |= ERR_ALERT | ERR_ABORT;
2492 goto out;
2493 }
2494
2495 err = invalid_char(args[1]);
2496 if (err) {
2497 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2498 file, linenum, *err, args[0], args[1]);
2499 err_code |= ERR_ALERT | ERR_ABORT;
2500 goto out;
2501 }
2502
2503 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2504 /*
2505 * If there are two proxies with the same name only following
2506 * combinations are allowed:
2507 */
2508 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002509 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 +09002510 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002511 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002512 }
2513 }
2514
2515 if ((curmailers = (struct mailers *)calloc(1, sizeof(struct mailers))) == NULL) {
2516 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2517 err_code |= ERR_ALERT | ERR_ABORT;
2518 goto out;
2519 }
2520
2521 curmailers->next = mailers;
2522 mailers = curmailers;
2523 curmailers->conf.file = strdup(file);
2524 curmailers->conf.line = linenum;
2525 curmailers->id = strdup(args[1]);
2526 }
2527 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2528 struct sockaddr_storage *sk;
2529 int port1, port2;
2530 struct protocol *proto;
2531
2532 if (!*args[2]) {
2533 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2534 file, linenum, args[0]);
2535 err_code |= ERR_ALERT | ERR_FATAL;
2536 goto out;
2537 }
2538
2539 err = invalid_char(args[1]);
2540 if (err) {
2541 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2542 file, linenum, *err, args[1]);
2543 err_code |= ERR_ALERT | ERR_FATAL;
2544 goto out;
2545 }
2546
2547 if ((newmailer = (struct mailer *)calloc(1, sizeof(struct mailer))) == NULL) {
2548 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2549 err_code |= ERR_ALERT | ERR_ABORT;
2550 goto out;
2551 }
2552
2553 /* the mailers are linked backwards first */
2554 curmailers->count++;
2555 newmailer->next = curmailers->mailer_list;
2556 curmailers->mailer_list = newmailer;
2557 newmailer->mailers = curmailers;
2558 newmailer->conf.file = strdup(file);
2559 newmailer->conf.line = linenum;
2560
2561 newmailer->id = strdup(args[1]);
2562
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002563 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002564 if (!sk) {
2565 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2566 err_code |= ERR_ALERT | ERR_FATAL;
2567 goto out;
2568 }
2569
2570 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002571 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2572 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002573 file, linenum, args[0], args[1]);
2574 err_code |= ERR_ALERT | ERR_FATAL;
2575 goto out;
2576 }
2577
2578 if (port1 != port2) {
2579 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2580 file, linenum, args[0], args[1], args[2]);
2581 err_code |= ERR_ALERT | ERR_FATAL;
2582 goto out;
2583 }
2584
2585 if (!port1) {
2586 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2587 file, linenum, args[0], args[1], args[2]);
2588 err_code |= ERR_ALERT | ERR_FATAL;
2589 goto out;
2590 }
2591
2592 newmailer->addr = *sk;
2593 newmailer->proto = proto;
2594 newmailer->xprt = &raw_sock;
2595 newmailer->sock_init_arg = NULL;
2596 } /* neither "mailer" nor "mailers" */
2597 else if (*args[0] != 0) {
2598 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2599 err_code |= ERR_ALERT | ERR_FATAL;
2600 goto out;
2601 }
2602
2603out:
2604 free(errmsg);
2605 return err_code;
2606}
2607
Simon Horman9dc49962015-01-30 11:22:59 +09002608static void free_email_alert(struct proxy *p)
2609{
2610 free(p->email_alert.mailers.name);
2611 p->email_alert.mailers.name = NULL;
2612 free(p->email_alert.from);
2613 p->email_alert.from = NULL;
2614 free(p->email_alert.to);
2615 p->email_alert.to = NULL;
2616 free(p->email_alert.myhostname);
2617 p->email_alert.myhostname = NULL;
2618}
2619
Willy Tarreau3842f002009-06-14 11:39:52 +02002620int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002621{
2622 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002623 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002624 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002625 int rc;
2626 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002627 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002628 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002629 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002630 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002631 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002632
Willy Tarreau977b8e42006-12-29 14:19:17 +01002633 if (!strcmp(args[0], "listen"))
2634 rc = PR_CAP_LISTEN;
2635 else if (!strcmp(args[0], "frontend"))
2636 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002637 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002638 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002639 else
2640 rc = PR_CAP_NONE;
2641
2642 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002643 if (!*args[1]) {
2644 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2645 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2646 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002647 err_code |= ERR_ALERT | ERR_ABORT;
2648 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002649 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002650
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002651 err = invalid_char(args[1]);
2652 if (err) {
2653 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2654 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002655 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002656 }
2657
Willy Tarreau8f50b682015-05-26 11:45:02 +02002658 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2659 if (curproxy) {
2660 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2661 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2662 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002663 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002664 }
2665
Willy Tarreaubaaee002006-06-26 02:48:02 +02002666 if ((curproxy = (struct proxy *)calloc(1, sizeof(struct proxy))) == NULL) {
2667 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002668 err_code |= ERR_ALERT | ERR_ABORT;
2669 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002670 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002671
Willy Tarreau97cb7802010-01-03 20:23:58 +01002672 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002673 curproxy->next = proxy;
2674 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002675 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2676 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002677 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002678 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002679 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002680 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002681
William Lallemand6e62fb62015-04-28 16:55:23 +02002682 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2683 if (curproxy->cap & PR_CAP_FE)
2684 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2685 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686 }
2687
2688 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002689 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002690 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002691
Willy Tarreaubaaee002006-06-26 02:48:02 +02002692 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002693 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002694 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002695 curproxy->no_options = defproxy.no_options;
2696 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002697 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002698 curproxy->except_net = defproxy.except_net;
2699 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002700 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002701 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002702
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002703 if (defproxy.fwdfor_hdr_len) {
2704 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2705 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2706 }
2707
Willy Tarreaub86db342009-11-30 11:50:16 +01002708 if (defproxy.orgto_hdr_len) {
2709 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2710 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2711 }
2712
Mark Lamourinec2247f02012-01-04 13:02:01 -05002713 if (defproxy.server_id_hdr_len) {
2714 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2715 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2716 }
2717
Willy Tarreau977b8e42006-12-29 14:19:17 +01002718 if (curproxy->cap & PR_CAP_FE) {
2719 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002720 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002721 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002722
2723 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002724 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2725 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002726
2727 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2728 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002729
Willy Tarreau977b8e42006-12-29 14:19:17 +01002730 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002731 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002732 curproxy->fullconn = defproxy.fullconn;
2733 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002734 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002735 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002736
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002737 if (defproxy.check_req) {
2738 curproxy->check_req = calloc(1, defproxy.check_len);
2739 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2740 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002741 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002743 if (defproxy.expect_str) {
2744 curproxy->expect_str = strdup(defproxy.expect_str);
2745 if (defproxy.expect_regex) {
2746 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002747 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2748 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002749 }
2750 }
2751
Willy Tarreau67402132012-05-31 20:40:20 +02002752 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002753 if (defproxy.cookie_name)
2754 curproxy->cookie_name = strdup(defproxy.cookie_name);
2755 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002756 if (defproxy.cookie_domain)
2757 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002758
Willy Tarreau31936852010-10-06 16:59:56 +02002759 if (defproxy.cookie_maxidle)
2760 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2761
2762 if (defproxy.cookie_maxlife)
2763 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2764
Emeric Brun647caf12009-06-30 17:57:00 +02002765 if (defproxy.rdp_cookie_name)
2766 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2767 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2768
Willy Tarreau01732802007-11-01 22:48:15 +01002769 if (defproxy.url_param_name)
2770 curproxy->url_param_name = strdup(defproxy.url_param_name);
2771 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002772
Benoitaffb4812009-03-25 13:02:10 +01002773 if (defproxy.hh_name)
2774 curproxy->hh_name = strdup(defproxy.hh_name);
2775 curproxy->hh_len = defproxy.hh_len;
2776 curproxy->hh_match_domain = defproxy.hh_match_domain;
2777
Willy Tarreauef9a3602012-12-08 22:29:20 +01002778 if (defproxy.conn_src.iface_name)
2779 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2780 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002781 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002782#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002783 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002784#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002785 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002787
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002788 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002789 if (defproxy.capture_name)
2790 curproxy->capture_name = strdup(defproxy.capture_name);
2791 curproxy->capture_namelen = defproxy.capture_namelen;
2792 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002796 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002797 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002798 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002799 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002800 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002801 curproxy->mon_net = defproxy.mon_net;
2802 curproxy->mon_mask = defproxy.mon_mask;
2803 if (defproxy.monitor_uri)
2804 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2805 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002806 if (defproxy.defbe.name)
2807 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002808
2809 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002810 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2811 if (curproxy->conf.logformat_string &&
2812 curproxy->conf.logformat_string != default_http_log_format &&
2813 curproxy->conf.logformat_string != default_tcp_log_format &&
2814 curproxy->conf.logformat_string != clf_http_log_format)
2815 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2816
2817 if (defproxy.conf.lfs_file) {
2818 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2819 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2820 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002821
2822 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2823 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2824 if (curproxy->conf.logformat_sd_string &&
2825 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2826 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2827
2828 if (defproxy.conf.lfsd_file) {
2829 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2830 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2831 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002832 }
2833
2834 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002835 curproxy->timeout.connect = defproxy.timeout.connect;
2836 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002837 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002838 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002839 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002840 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002841 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002842 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002843 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002844 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002845 }
2846
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002848 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002849
2850 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002851 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02002852 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01002853 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002854 LIST_INIT(&node->list);
2855 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2856 }
2857
Willy Tarreau62a61232013-04-12 18:13:46 +02002858 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2859 if (curproxy->conf.uniqueid_format_string)
2860 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2861
Dragan Dosen43885c72015-10-01 13:18:13 +02002862 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002863
Willy Tarreau62a61232013-04-12 18:13:46 +02002864 if (defproxy.conf.uif_file) {
2865 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2866 curproxy->conf.uif_line = defproxy.conf.uif_line;
2867 }
William Lallemanda73203e2012-03-12 12:48:57 +01002868
2869 /* copy default header unique id */
2870 if (defproxy.header_unique_id)
2871 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2872
William Lallemand82fe75c2012-10-23 10:25:10 +02002873 /* default compression options */
2874 if (defproxy.comp != NULL) {
2875 curproxy->comp = calloc(1, sizeof(struct comp));
2876 curproxy->comp->algos = defproxy.comp->algos;
2877 curproxy->comp->types = defproxy.comp->types;
2878 }
2879
Willy Tarreaubaaee002006-06-26 02:48:02 +02002880 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002881 curproxy->conf.used_listener_id = EB_ROOT;
2882 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002883
Simon Horman98637e52014-06-20 12:30:16 +09002884 if (defproxy.check_path)
2885 curproxy->check_path = strdup(defproxy.check_path);
2886 if (defproxy.check_command)
2887 curproxy->check_command = strdup(defproxy.check_command);
2888
Simon Horman9dc49962015-01-30 11:22:59 +09002889 if (defproxy.email_alert.mailers.name)
2890 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2891 if (defproxy.email_alert.from)
2892 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2893 if (defproxy.email_alert.to)
2894 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2895 if (defproxy.email_alert.myhostname)
2896 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002897 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002898 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002899
Willy Tarreau93893792009-07-23 13:19:11 +02002900 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002901 }
2902 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2903 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002904 /* FIXME-20070101: we should do this too at the end of the
2905 * config parsing to free all default values.
2906 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002907 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2908 err_code |= ERR_ABORT;
2909 goto out;
2910 }
2911
Willy Tarreaua534fea2008-08-03 12:19:50 +02002912 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002913 free(defproxy.check_command);
2914 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002915 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002916 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002917 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002918 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002919 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002920 free(defproxy.capture_name);
2921 free(defproxy.monitor_uri);
2922 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002923 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002924 free(defproxy.fwdfor_hdr_name);
2925 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002926 free(defproxy.orgto_hdr_name);
2927 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002928 free(defproxy.server_id_hdr_name);
2929 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002930 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002931 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002932 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002933 free(defproxy.expect_regex);
2934 defproxy.expect_regex = NULL;
2935 }
Willy Tarreau0f772532006-12-23 20:51:41 +01002936
Willy Tarreau62a61232013-04-12 18:13:46 +02002937 if (defproxy.conf.logformat_string != default_http_log_format &&
2938 defproxy.conf.logformat_string != default_tcp_log_format &&
2939 defproxy.conf.logformat_string != clf_http_log_format)
2940 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02002941
Willy Tarreau62a61232013-04-12 18:13:46 +02002942 free(defproxy.conf.uniqueid_format_string);
2943 free(defproxy.conf.lfs_file);
2944 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02002945 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09002946 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02002947
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002948 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
2949 free(defproxy.conf.logformat_sd_string);
2950 free(defproxy.conf.lfsd_file);
2951
Willy Tarreaua534fea2008-08-03 12:19:50 +02002952 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002953 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01002954
Willy Tarreaubaaee002006-06-26 02:48:02 +02002955 /* we cannot free uri_auth because it might already be used */
2956 init_default_instance();
2957 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002958 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2959 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002960 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02002961 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002962 }
2963 else if (curproxy == NULL) {
2964 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002965 err_code |= ERR_ALERT | ERR_FATAL;
2966 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002967 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002968
2969 /* update the current file and line being parsed */
2970 curproxy->conf.args.file = curproxy->conf.file;
2971 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002972
2973 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02002974 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
2975 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
2976 if (err_code & ERR_FATAL)
2977 goto out;
2978 }
2979 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02002980 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01002981 int cur_arg;
2982
Willy Tarreaubaaee002006-06-26 02:48:02 +02002983 if (curproxy == &defproxy) {
2984 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002985 err_code |= ERR_ALERT | ERR_FATAL;
2986 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002987 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002988 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02002989 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002990
Willy Tarreau24709282013-03-10 21:32:12 +01002991 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01002992 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002993 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002994 err_code |= ERR_ALERT | ERR_FATAL;
2995 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002996 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01002997
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002998 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01002999
3000 /* use default settings for unix sockets */
3001 bind_conf->ux.uid = global.unix_bind.ux.uid;
3002 bind_conf->ux.gid = global.unix_bind.ux.gid;
3003 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003004
3005 /* NOTE: the following line might create several listeners if there
3006 * are comma-separated IPs or port ranges. So all further processing
3007 * will have to be applied to all listeners created after last_listen.
3008 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003009 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3010 if (errmsg && *errmsg) {
3011 indent_msg(&errmsg, 2);
3012 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003013 }
3014 else
3015 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3016 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003017 err_code |= ERR_ALERT | ERR_FATAL;
3018 goto out;
3019 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003020
Willy Tarreau4348fad2012-09-20 16:48:07 +02003021 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3022 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003023 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003024 }
3025
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003026 cur_arg = 2;
3027 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003028 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003029 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003030 char *err;
3031
Willy Tarreau26982662012-09-12 23:17:10 +02003032 kw = bind_find_kw(args[cur_arg]);
3033 if (kw) {
3034 char *err = NULL;
3035 int code;
3036
3037 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003038 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3039 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003040 cur_arg += 1 + kw->skip ;
3041 err_code |= ERR_ALERT | ERR_FATAL;
3042 goto out;
3043 }
3044
Willy Tarreau4348fad2012-09-20 16:48:07 +02003045 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003046 err_code |= code;
3047
3048 if (code) {
3049 if (err && *err) {
3050 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003051 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003052 }
3053 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003054 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3055 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003056 if (code & ERR_FATAL) {
3057 free(err);
3058 cur_arg += 1 + kw->skip;
3059 goto out;
3060 }
3061 }
3062 free(err);
3063 cur_arg += 1 + kw->skip;
3064 continue;
3065 }
3066
Willy Tarreau8638f482012-09-18 18:01:17 +02003067 err = NULL;
3068 if (!bind_dumped) {
3069 bind_dump_kws(&err);
3070 indent_msg(&err, 4);
3071 bind_dumped = 1;
3072 }
3073
3074 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3075 file, linenum, args[0], args[1], args[cur_arg],
3076 err ? " Registered keywords :" : "", err ? err : "");
3077 free(err);
3078
Willy Tarreau93893792009-07-23 13:19:11 +02003079 err_code |= ERR_ALERT | ERR_FATAL;
3080 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003081 }
Willy Tarreau93893792009-07-23 13:19:11 +02003082 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003083 }
3084 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003085 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003086 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3087 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003088 err_code |= ERR_ALERT | ERR_FATAL;
3089 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003090 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003091 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003092 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003093
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 /* flush useless bits */
3095 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003097 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003098 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003099 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003101
William Lallemanddf1425a2015-04-28 20:17:49 +02003102 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3103 goto out;
3104
Willy Tarreau1c47f852006-07-09 08:22:27 +02003105 if (!*args[1]) {
3106 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3107 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003108 err_code |= ERR_ALERT | ERR_FATAL;
3109 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003110 }
3111
Willy Tarreaua534fea2008-08-03 12:19:50 +02003112 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003113 curproxy->monitor_uri_len = strlen(args[1]);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003114 curproxy->monitor_uri = (char *)calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003115 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003116 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3117
Willy Tarreau93893792009-07-23 13:19:11 +02003118 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003119 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003120 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003121 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3122 goto out;
3123
Willy Tarreaubaaee002006-06-26 02:48:02 +02003124 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3125 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3126 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3127 else {
3128 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003129 err_code |= ERR_ALERT | ERR_FATAL;
3130 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003131 }
3132 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003133 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003134 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003135
3136 if (curproxy == &defproxy) {
3137 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3138 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003139 err_code |= ERR_ALERT | ERR_FATAL;
3140 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003141 }
3142
William Lallemanddf1425a2015-04-28 20:17:49 +02003143 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3144 goto out;
3145
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003146 if (!*args[1]) {
3147 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3148 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003149 err_code |= ERR_ALERT | ERR_FATAL;
3150 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003151 }
3152
3153 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003154 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003155 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003156
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003157 if (curproxy->uuid <= 0) {
3158 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003159 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003160 err_code |= ERR_ALERT | ERR_FATAL;
3161 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003162 }
3163
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003164 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3165 if (node) {
3166 struct proxy *target = container_of(node, struct proxy, conf.id);
3167 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3168 file, linenum, proxy_type_str(curproxy), curproxy->id,
3169 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3170 err_code |= ERR_ALERT | ERR_FATAL;
3171 goto out;
3172 }
3173 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003174 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003175 else if (!strcmp(args[0], "description")) {
3176 int i, len=0;
3177 char *d;
3178
Cyril Bonté99ed3272010-01-24 23:29:44 +01003179 if (curproxy == &defproxy) {
3180 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3181 file, linenum, args[0]);
3182 err_code |= ERR_ALERT | ERR_FATAL;
3183 goto out;
3184 }
3185
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003186 if (!*args[1]) {
3187 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3188 file, linenum, args[0]);
3189 return -1;
3190 }
3191
Willy Tarreau348acfe2014-04-14 15:00:39 +02003192 for (i = 1; *args[i]; i++)
3193 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003194
3195 d = (char *)calloc(1, len);
3196 curproxy->desc = d;
3197
Willy Tarreau348acfe2014-04-14 15:00:39 +02003198 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3199 for (i = 2; *args[i]; i++)
3200 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003201
3202 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003203 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003204 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3205 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003206 curproxy->state = PR_STSTOPPED;
3207 }
3208 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003209 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3210 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003211 curproxy->state = PR_STNEW;
3212 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003213 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3214 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003215 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003216
3217 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003218 unsigned int low, high;
3219
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003220 if (strcmp(args[cur_arg], "all") == 0) {
3221 set = 0;
3222 break;
3223 }
3224 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003225 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003226 }
3227 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003228 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003229 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003230 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003231 char *dash = strchr(args[cur_arg], '-');
3232
3233 low = high = str2uic(args[cur_arg]);
3234 if (dash)
3235 high = str2uic(dash + 1);
3236
3237 if (high < low) {
3238 unsigned int swap = low;
3239 low = high;
3240 high = swap;
3241 }
3242
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003243 if (low < 1 || high > LONGBITS) {
3244 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3245 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003246 err_code |= ERR_ALERT | ERR_FATAL;
3247 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003248 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003249 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003250 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003251 }
3252 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003253 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3254 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003255 err_code |= ERR_ALERT | ERR_FATAL;
3256 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003257 }
3258 cur_arg++;
3259 }
3260 curproxy->bind_proc = set;
3261 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003262 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003263 if (curproxy == &defproxy) {
3264 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003265 err_code |= ERR_ALERT | ERR_FATAL;
3266 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003267 }
3268
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003269 err = invalid_char(args[1]);
3270 if (err) {
3271 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3272 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003273 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003274 }
3275
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003276 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003277 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3278 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003279 err_code |= ERR_ALERT | ERR_FATAL;
3280 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003281 }
3282 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003283 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3284 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003285
Willy Tarreau977b8e42006-12-29 14:19:17 +01003286 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003287 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003288
Willy Tarreaubaaee002006-06-26 02:48:02 +02003289 if (*(args[1]) == 0) {
3290 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3291 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003292 err_code |= ERR_ALERT | ERR_FATAL;
3293 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003294 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003295
Willy Tarreau67402132012-05-31 20:40:20 +02003296 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003297 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003298 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003299 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003300 curproxy->cookie_name = strdup(args[1]);
3301 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003302
Willy Tarreaubaaee002006-06-26 02:48:02 +02003303 cur_arg = 2;
3304 while (*(args[cur_arg])) {
3305 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003306 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003307 }
3308 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003309 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003310 }
3311 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003312 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003313 }
3314 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003315 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003316 }
3317 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003318 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003319 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003320 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003321 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003322 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003323 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003324 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003325 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003326 else if (!strcmp(args[cur_arg], "httponly")) {
3327 curproxy->ck_opts |= PR_CK_HTTPONLY;
3328 }
3329 else if (!strcmp(args[cur_arg], "secure")) {
3330 curproxy->ck_opts |= PR_CK_SECURE;
3331 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003332 else if (!strcmp(args[cur_arg], "domain")) {
3333 if (!*args[cur_arg + 1]) {
3334 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3335 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003336 err_code |= ERR_ALERT | ERR_FATAL;
3337 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003338 }
3339
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003340 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003341 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003342 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3343 " dots nor does not start with a dot."
3344 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003345 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003346 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003347 }
3348
3349 err = invalid_domainchar(args[cur_arg + 1]);
3350 if (err) {
3351 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3352 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003353 err_code |= ERR_ALERT | ERR_FATAL;
3354 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003355 }
3356
Willy Tarreau68a897b2009-12-03 23:28:34 +01003357 if (!curproxy->cookie_domain) {
3358 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3359 } else {
3360 /* one domain was already specified, add another one by
3361 * building the string which will be returned along with
3362 * the cookie.
3363 */
3364 char *new_ptr;
3365 int new_len = strlen(curproxy->cookie_domain) +
3366 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3367 new_ptr = malloc(new_len);
3368 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3369 free(curproxy->cookie_domain);
3370 curproxy->cookie_domain = new_ptr;
3371 }
Willy Tarreau31936852010-10-06 16:59:56 +02003372 cur_arg++;
3373 }
3374 else if (!strcmp(args[cur_arg], "maxidle")) {
3375 unsigned int maxidle;
3376 const char *res;
3377
3378 if (!*args[cur_arg + 1]) {
3379 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3380 file, linenum, args[cur_arg]);
3381 err_code |= ERR_ALERT | ERR_FATAL;
3382 goto out;
3383 }
3384
3385 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3386 if (res) {
3387 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3388 file, linenum, *res, args[cur_arg]);
3389 err_code |= ERR_ALERT | ERR_FATAL;
3390 goto out;
3391 }
3392 curproxy->cookie_maxidle = maxidle;
3393 cur_arg++;
3394 }
3395 else if (!strcmp(args[cur_arg], "maxlife")) {
3396 unsigned int maxlife;
3397 const char *res;
3398
3399 if (!*args[cur_arg + 1]) {
3400 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3401 file, linenum, args[cur_arg]);
3402 err_code |= ERR_ALERT | ERR_FATAL;
3403 goto out;
3404 }
3405
3406 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3407 if (res) {
3408 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3409 file, linenum, *res, args[cur_arg]);
3410 err_code |= ERR_ALERT | ERR_FATAL;
3411 goto out;
3412 }
3413 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003414 cur_arg++;
3415 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003416 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003417 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 +02003418 file, linenum, args[0]);
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 cur_arg++;
3423 }
Willy Tarreau67402132012-05-31 20:40:20 +02003424 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003425 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3426 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003427 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003428 }
3429
Willy Tarreau67402132012-05-31 20:40:20 +02003430 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003431 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3432 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003433 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003435
Willy Tarreau67402132012-05-31 20:40:20 +02003436 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003437 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3438 file, linenum);
3439 err_code |= ERR_ALERT | ERR_FATAL;
3440 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003441 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003442 else if (!strcmp(args[0], "email-alert")) {
3443 if (*(args[1]) == 0) {
3444 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3445 file, linenum, args[0]);
3446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
3448 }
3449
3450 if (!strcmp(args[1], "from")) {
3451 if (*(args[1]) == 0) {
3452 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3453 file, linenum, args[1]);
3454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
3456 }
3457 free(curproxy->email_alert.from);
3458 curproxy->email_alert.from = strdup(args[2]);
3459 }
3460 else if (!strcmp(args[1], "mailers")) {
3461 if (*(args[1]) == 0) {
3462 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3463 file, linenum, args[1]);
3464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
3466 }
3467 free(curproxy->email_alert.mailers.name);
3468 curproxy->email_alert.mailers.name = strdup(args[2]);
3469 }
3470 else if (!strcmp(args[1], "myhostname")) {
3471 if (*(args[1]) == 0) {
3472 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3473 file, linenum, args[1]);
3474 err_code |= ERR_ALERT | ERR_FATAL;
3475 goto out;
3476 }
3477 free(curproxy->email_alert.myhostname);
3478 curproxy->email_alert.myhostname = strdup(args[2]);
3479 }
Simon Horman64e34162015-02-06 11:11:57 +09003480 else if (!strcmp(args[1], "level")) {
3481 curproxy->email_alert.level = get_log_level(args[2]);
3482 if (curproxy->email_alert.level < 0) {
3483 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3484 file, linenum, args[1], args[2]);
3485 err_code |= ERR_ALERT | ERR_FATAL;
3486 goto out;
3487 }
3488 }
Simon Horman9dc49962015-01-30 11:22:59 +09003489 else if (!strcmp(args[1], "to")) {
3490 if (*(args[1]) == 0) {
3491 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3492 file, linenum, args[1]);
3493 err_code |= ERR_ALERT | ERR_FATAL;
3494 goto out;
3495 }
3496 free(curproxy->email_alert.to);
3497 curproxy->email_alert.to = strdup(args[2]);
3498 }
3499 else {
3500 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3501 file, linenum, args[1]);
3502 err_code |= ERR_ALERT | ERR_FATAL;
3503 goto out;
3504 }
Simon Horman64e34162015-02-06 11:11:57 +09003505 /* Indicate that the email_alert is at least partially configured */
3506 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003507 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003508 else if (!strcmp(args[0], "external-check")) {
3509 if (*(args[1]) == 0) {
3510 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3511 file, linenum, args[0]);
3512 err_code |= ERR_ALERT | ERR_FATAL;
3513 goto out;
3514 }
3515
3516 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003517 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003518 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003519 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003520 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3521 file, linenum, args[1]);
3522 err_code |= ERR_ALERT | ERR_FATAL;
3523 goto out;
3524 }
3525 free(curproxy->check_command);
3526 curproxy->check_command = strdup(args[2]);
3527 }
3528 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003529 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003530 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003531 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003532 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3533 file, linenum, args[1]);
3534 err_code |= ERR_ALERT | ERR_FATAL;
3535 goto out;
3536 }
3537 free(curproxy->check_path);
3538 curproxy->check_path = strdup(args[2]);
3539 }
3540 else {
3541 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3542 file, linenum, args[1]);
3543 err_code |= ERR_ALERT | ERR_FATAL;
3544 goto out;
3545 }
3546 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003547 else if (!strcmp(args[0], "persist")) { /* persist */
3548 if (*(args[1]) == 0) {
3549 Alert("parsing [%s:%d] : missing persist method.\n",
3550 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003551 err_code |= ERR_ALERT | ERR_FATAL;
3552 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003553 }
3554
3555 if (!strncmp(args[1], "rdp-cookie", 10)) {
3556 curproxy->options2 |= PR_O2_RDPC_PRST;
3557
Emeric Brunb982a3d2010-01-04 15:45:53 +01003558 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003559 const char *beg, *end;
3560
3561 beg = args[1] + 11;
3562 end = strchr(beg, ')');
3563
William Lallemanddf1425a2015-04-28 20:17:49 +02003564 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3565 goto out;
3566
Emeric Brun647caf12009-06-30 17:57:00 +02003567 if (!end || end == beg) {
3568 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3569 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003570 err_code |= ERR_ALERT | ERR_FATAL;
3571 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003572 }
3573
3574 free(curproxy->rdp_cookie_name);
3575 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3576 curproxy->rdp_cookie_len = end-beg;
3577 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003578 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003579 free(curproxy->rdp_cookie_name);
3580 curproxy->rdp_cookie_name = strdup("msts");
3581 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3582 }
3583 else { /* syntax */
3584 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3585 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003586 err_code |= ERR_ALERT | ERR_FATAL;
3587 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003588 }
3589 }
3590 else {
3591 Alert("parsing [%s:%d] : unknown persist method.\n",
3592 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003593 err_code |= ERR_ALERT | ERR_FATAL;
3594 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003595 }
3596 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003597 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003598 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
3601 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003602 else if (!strcmp(args[0], "load-server-state-from-file")) {
3603 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3604 err_code |= ERR_WARN;
3605 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3606 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3607 }
3608 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3609 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3610 }
3611 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3612 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3613 }
3614 else {
3615 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3616 file, linenum, args[0], args[1]);
3617 err_code |= ERR_ALERT | ERR_FATAL;
3618 goto out;
3619 }
3620 }
3621 else if (!strcmp(args[0], "server-state-file-name")) {
3622 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3623 err_code |= ERR_WARN;
3624 if (*(args[1]) == 0) {
3625 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3626 file, linenum, args[0]);
3627 err_code |= ERR_ALERT | ERR_FATAL;
3628 goto out;
3629 }
3630 else if (!strcmp(args[1], "use-backend-name"))
3631 curproxy->server_state_file_name = strdup(curproxy->id);
3632 else
3633 curproxy->server_state_file_name = strdup(args[1]);
3634 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003635 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003636 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003637 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003638
Willy Tarreaubaaee002006-06-26 02:48:02 +02003639 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003640 if (curproxy == &defproxy) {
3641 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3642 err_code |= ERR_ALERT | ERR_FATAL;
3643 goto out;
3644 }
3645
William Lallemand1a748ae2015-05-19 16:37:23 +02003646 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3647 goto out;
3648
Willy Tarreaubaaee002006-06-26 02:48:02 +02003649 if (*(args[4]) == 0) {
3650 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3651 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003652 err_code |= ERR_ALERT | ERR_FATAL;
3653 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003654 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003655 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003656 curproxy->capture_name = strdup(args[2]);
3657 curproxy->capture_namelen = strlen(curproxy->capture_name);
3658 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003659 curproxy->to_log |= LW_COOKIE;
3660 }
3661 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3662 struct cap_hdr *hdr;
3663
3664 if (curproxy == &defproxy) {
3665 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 +02003666 err_code |= ERR_ALERT | ERR_FATAL;
3667 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003668 }
3669
William Lallemand1a748ae2015-05-19 16:37:23 +02003670 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3671 goto out;
3672
Willy Tarreaubaaee002006-06-26 02:48:02 +02003673 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3674 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3675 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003676 err_code |= ERR_ALERT | ERR_FATAL;
3677 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003678 }
3679
3680 hdr = calloc(sizeof(struct cap_hdr), 1);
3681 hdr->next = curproxy->req_cap;
3682 hdr->name = strdup(args[3]);
3683 hdr->namelen = strlen(args[3]);
3684 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003685 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003686 hdr->index = curproxy->nb_req_cap++;
3687 curproxy->req_cap = hdr;
3688 curproxy->to_log |= LW_REQHDR;
3689 }
3690 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3691 struct cap_hdr *hdr;
3692
3693 if (curproxy == &defproxy) {
3694 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 +02003695 err_code |= ERR_ALERT | ERR_FATAL;
3696 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003697 }
3698
William Lallemand1a748ae2015-05-19 16:37:23 +02003699 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3700 goto out;
3701
Willy Tarreaubaaee002006-06-26 02:48:02 +02003702 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3703 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3704 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003705 err_code |= ERR_ALERT | ERR_FATAL;
3706 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003707 }
3708 hdr = calloc(sizeof(struct cap_hdr), 1);
3709 hdr->next = curproxy->rsp_cap;
3710 hdr->name = strdup(args[3]);
3711 hdr->namelen = strlen(args[3]);
3712 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003713 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 hdr->index = curproxy->nb_rsp_cap++;
3715 curproxy->rsp_cap = hdr;
3716 curproxy->to_log |= LW_RSPHDR;
3717 }
3718 else {
3719 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3720 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003721 err_code |= ERR_ALERT | ERR_FATAL;
3722 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003723 }
3724 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003725 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003726 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003727 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003728
William Lallemanddf1425a2015-04-28 20:17:49 +02003729 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3730 goto out;
3731
Willy Tarreaubaaee002006-06-26 02:48:02 +02003732 if (*(args[1]) == 0) {
3733 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3734 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003735 err_code |= ERR_ALERT | ERR_FATAL;
3736 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003737 }
3738 curproxy->conn_retries = atol(args[1]);
3739 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003740 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003741 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003742
3743 if (curproxy == &defproxy) {
3744 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3745 err_code |= ERR_ALERT | ERR_FATAL;
3746 goto out;
3747 }
3748
Willy Tarreau20b0de52012-12-24 15:45:22 +01003749 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003750 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003751 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3752 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3753 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3754 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003755 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 +01003756 file, linenum, args[0]);
3757 err_code |= ERR_WARN;
3758 }
3759
Willy Tarreauff011f22011-01-06 17:51:27 +01003760 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003761
Willy Tarreauff011f22011-01-06 17:51:27 +01003762 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003763 err_code |= ERR_ALERT | ERR_ABORT;
3764 goto out;
3765 }
3766
Willy Tarreau5002f572014-04-23 01:32:02 +02003767 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003768 err_code |= warnif_cond_conflicts(rule->cond,
3769 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3770 file, linenum);
3771
Willy Tarreauff011f22011-01-06 17:51:27 +01003772 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003773 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003774 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003775 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003776
3777 if (curproxy == &defproxy) {
3778 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3779 err_code |= ERR_ALERT | ERR_FATAL;
3780 goto out;
3781 }
3782
3783 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003784 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003785 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3786 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003787 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3788 file, linenum, args[0]);
3789 err_code |= ERR_WARN;
3790 }
3791
3792 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3793
3794 if (!rule) {
3795 err_code |= ERR_ALERT | ERR_ABORT;
3796 goto out;
3797 }
3798
3799 err_code |= warnif_cond_conflicts(rule->cond,
3800 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3801 file, linenum);
3802
3803 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3804 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003805 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3806 /* set the header name and length into the proxy structure */
3807 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3808 err_code |= ERR_WARN;
3809
3810 if (!*args[1]) {
3811 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3812 file, linenum, args[0]);
3813 err_code |= ERR_ALERT | ERR_FATAL;
3814 goto out;
3815 }
3816
3817 /* set the desired header name */
3818 free(curproxy->server_id_hdr_name);
3819 curproxy->server_id_hdr_name = strdup(args[1]);
3820 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3821 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003822 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003823 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003824
Willy Tarreaub099aca2008-10-12 17:26:37 +02003825 if (curproxy == &defproxy) {
3826 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003827 err_code |= ERR_ALERT | ERR_FATAL;
3828 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003829 }
3830
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003831 /* emulate "block" using "http-request block". Since these rules are supposed to
3832 * be processed before all http-request rules, we put them into their own list
3833 * and will insert them at the end.
3834 */
3835 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3836 if (!rule) {
3837 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003838 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003839 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003840 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3841 err_code |= warnif_cond_conflicts(rule->cond,
3842 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3843 file, linenum);
3844 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003845
3846 if (!already_warned(WARN_BLOCK_DEPRECATED))
3847 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]);
3848
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003849 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003850 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003851 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003852
Cyril Bonté99ed3272010-01-24 23:29:44 +01003853 if (curproxy == &defproxy) {
3854 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3855 err_code |= ERR_ALERT | ERR_FATAL;
3856 goto out;
3857 }
3858
Willy Tarreaube4653b2015-05-28 15:26:58 +02003859 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003860 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3861 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003862 err_code |= ERR_ALERT | ERR_FATAL;
3863 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003864 }
3865
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003866 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003867 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003868 err_code |= warnif_cond_conflicts(rule->cond,
3869 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3870 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003871 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003872 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003873 struct switching_rule *rule;
3874
Willy Tarreaub099aca2008-10-12 17:26:37 +02003875 if (curproxy == &defproxy) {
3876 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003877 err_code |= ERR_ALERT | ERR_FATAL;
3878 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003879 }
3880
Willy Tarreau55ea7572007-06-17 19:56:27 +02003881 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003882 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003883
3884 if (*(args[1]) == 0) {
3885 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003886 err_code |= ERR_ALERT | ERR_FATAL;
3887 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003888 }
3889
Willy Tarreauf51658d2014-04-23 01:21:56 +02003890 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3891 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3892 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3893 file, linenum, errmsg);
3894 err_code |= ERR_ALERT | ERR_FATAL;
3895 goto out;
3896 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003897
Willy Tarreauf51658d2014-04-23 01:21:56 +02003898 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003899 }
3900
3901 rule = (struct switching_rule *)calloc(1, sizeof(*rule));
3902 rule->cond = cond;
3903 rule->be.name = strdup(args[1]);
3904 LIST_INIT(&rule->list);
3905 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3906 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003907 else if (strcmp(args[0], "use-server") == 0) {
3908 struct server_rule *rule;
3909
3910 if (curproxy == &defproxy) {
3911 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3912 err_code |= ERR_ALERT | ERR_FATAL;
3913 goto out;
3914 }
3915
3916 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3917 err_code |= ERR_WARN;
3918
3919 if (*(args[1]) == 0) {
3920 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3921 err_code |= ERR_ALERT | ERR_FATAL;
3922 goto out;
3923 }
3924
3925 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3926 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3927 file, linenum, args[0]);
3928 err_code |= ERR_ALERT | ERR_FATAL;
3929 goto out;
3930 }
3931
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003932 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3933 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3934 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003935 err_code |= ERR_ALERT | ERR_FATAL;
3936 goto out;
3937 }
3938
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003939 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003940
3941 rule = (struct server_rule *)calloc(1, sizeof(*rule));
3942 rule->cond = cond;
3943 rule->srv.name = strdup(args[1]);
3944 LIST_INIT(&rule->list);
3945 LIST_ADDQ(&curproxy->server_rules, &rule->list);
3946 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
3947 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003948 else if ((!strcmp(args[0], "force-persist")) ||
3949 (!strcmp(args[0], "ignore-persist"))) {
3950 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01003951
3952 if (curproxy == &defproxy) {
3953 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3954 err_code |= ERR_ALERT | ERR_FATAL;
3955 goto out;
3956 }
3957
3958 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
3959 err_code |= ERR_WARN;
3960
Willy Tarreauef6494c2010-01-28 17:12:36 +01003961 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01003962 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3963 file, linenum, args[0]);
3964 err_code |= ERR_ALERT | ERR_FATAL;
3965 goto out;
3966 }
3967
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003968 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
3969 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
3970 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01003971 err_code |= ERR_ALERT | ERR_FATAL;
3972 goto out;
3973 }
3974
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003975 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
3976 * where force-persist is applied.
3977 */
3978 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01003979
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003980 rule = (struct persist_rule *)calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01003981 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003982 if (!strcmp(args[0], "force-persist")) {
3983 rule->type = PERSIST_TYPE_FORCE;
3984 } else {
3985 rule->type = PERSIST_TYPE_IGNORE;
3986 }
Willy Tarreau4de91492010-01-22 19:10:05 +01003987 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02003988 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01003989 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003990 else if (!strcmp(args[0], "stick-table")) {
3991 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02003992 struct proxy *other;
3993
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02003994 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02003995 if (other) {
3996 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
3997 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
3998 err_code |= ERR_ALERT | ERR_FATAL;
3999 goto out;
4000 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004001
Emeric Brun32da3c42010-09-23 18:39:19 +02004002 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004003 curproxy->table.type = (unsigned int)-1;
4004 while (*args[myidx]) {
4005 const char *err;
4006
4007 if (strcmp(args[myidx], "size") == 0) {
4008 myidx++;
4009 if (!*(args[myidx])) {
4010 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4011 file, linenum, args[myidx-1]);
4012 err_code |= ERR_ALERT | ERR_FATAL;
4013 goto out;
4014 }
4015 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4016 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4017 file, linenum, *err, args[myidx-1]);
4018 err_code |= ERR_ALERT | ERR_FATAL;
4019 goto out;
4020 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004021 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004022 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004023 else if (strcmp(args[myidx], "peers") == 0) {
4024 myidx++;
Godbach50523162013-12-11 19:48:57 +08004025 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004026 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4027 file, linenum, args[myidx-1]);
4028 err_code |= ERR_ALERT | ERR_FATAL;
4029 goto out;
Godbach50523162013-12-11 19:48:57 +08004030 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004031 curproxy->table.peers.name = strdup(args[myidx++]);
4032 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004033 else if (strcmp(args[myidx], "expire") == 0) {
4034 myidx++;
4035 if (!*(args[myidx])) {
4036 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4037 file, linenum, args[myidx-1]);
4038 err_code |= ERR_ALERT | ERR_FATAL;
4039 goto out;
4040 }
4041 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4042 if (err) {
4043 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4044 file, linenum, *err, args[myidx-1]);
4045 err_code |= ERR_ALERT | ERR_FATAL;
4046 goto out;
4047 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004048 if (val > INT_MAX) {
4049 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4050 file, linenum, val);
4051 err_code |= ERR_ALERT | ERR_FATAL;
4052 goto out;
4053 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004054 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004055 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004056 }
4057 else if (strcmp(args[myidx], "nopurge") == 0) {
4058 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004059 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004060 }
4061 else if (strcmp(args[myidx], "type") == 0) {
4062 myidx++;
4063 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4064 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4065 file, linenum, args[myidx]);
4066 err_code |= ERR_ALERT | ERR_FATAL;
4067 goto out;
4068 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004069 /* myidx already points to next arg */
4070 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004071 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004072 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004073 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004074
4075 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004076 nw = args[myidx];
4077 while (*nw) {
4078 /* the "store" keyword supports a comma-separated list */
4079 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004080 sa = NULL; /* store arg */
4081 while (*nw && *nw != ',') {
4082 if (*nw == '(') {
4083 *nw = 0;
4084 sa = ++nw;
4085 while (*nw != ')') {
4086 if (!*nw) {
4087 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4088 file, linenum, args[0], cw);
4089 err_code |= ERR_ALERT | ERR_FATAL;
4090 goto out;
4091 }
4092 nw++;
4093 }
4094 *nw = '\0';
4095 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004096 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004097 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004098 if (*nw)
4099 *nw++ = '\0';
4100 type = stktable_get_data_type(cw);
4101 if (type < 0) {
4102 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4103 file, linenum, args[0], cw);
4104 err_code |= ERR_ALERT | ERR_FATAL;
4105 goto out;
4106 }
Willy Tarreauac782882010-06-20 10:41:54 +02004107
4108 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4109 switch (err) {
4110 case PE_NONE: break;
4111 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004112 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4113 file, linenum, args[0], cw);
4114 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004115 break;
4116
4117 case PE_ARG_MISSING:
4118 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4119 file, linenum, args[0], cw);
4120 err_code |= ERR_ALERT | ERR_FATAL;
4121 goto out;
4122
4123 case PE_ARG_NOT_USED:
4124 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4125 file, linenum, args[0], cw);
4126 err_code |= ERR_ALERT | ERR_FATAL;
4127 goto out;
4128
4129 default:
4130 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4131 file, linenum, args[0], cw);
4132 err_code |= ERR_ALERT | ERR_FATAL;
4133 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004134 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004135 }
4136 myidx++;
4137 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004138 else {
4139 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4140 file, linenum, args[myidx]);
4141 err_code |= ERR_ALERT | ERR_FATAL;
4142 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004143 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004144 }
4145
4146 if (!curproxy->table.size) {
4147 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4148 file, linenum);
4149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
4151 }
4152
4153 if (curproxy->table.type == (unsigned int)-1) {
4154 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4155 file, linenum);
4156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
4158 }
4159 }
4160 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004161 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004162 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004163 int myidx = 0;
4164 const char *name = NULL;
4165 int flags;
4166
4167 if (curproxy == &defproxy) {
4168 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
4171 }
4172
4173 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4174 err_code |= ERR_WARN;
4175 goto out;
4176 }
4177
4178 myidx++;
4179 if ((strcmp(args[myidx], "store") == 0) ||
4180 (strcmp(args[myidx], "store-request") == 0)) {
4181 myidx++;
4182 flags = STK_IS_STORE;
4183 }
4184 else if (strcmp(args[myidx], "store-response") == 0) {
4185 myidx++;
4186 flags = STK_IS_STORE | STK_ON_RSP;
4187 }
4188 else if (strcmp(args[myidx], "match") == 0) {
4189 myidx++;
4190 flags = STK_IS_MATCH;
4191 }
4192 else if (strcmp(args[myidx], "on") == 0) {
4193 myidx++;
4194 flags = STK_IS_MATCH | STK_IS_STORE;
4195 }
4196 else {
4197 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4198 err_code |= ERR_ALERT | ERR_FATAL;
4199 goto out;
4200 }
4201
4202 if (*(args[myidx]) == 0) {
4203 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4204 err_code |= ERR_ALERT | ERR_FATAL;
4205 goto out;
4206 }
4207
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004208 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004209 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004210 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004211 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004212 err_code |= ERR_ALERT | ERR_FATAL;
4213 goto out;
4214 }
4215
4216 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004217 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4218 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4219 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004220 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004221 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004222 goto out;
4223 }
4224 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004225 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4226 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4227 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004228 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004229 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004230 goto out;
4231 }
4232 }
4233
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004234 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004235 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004236
Emeric Brunb982a3d2010-01-04 15:45:53 +01004237 if (strcmp(args[myidx], "table") == 0) {
4238 myidx++;
4239 name = args[myidx++];
4240 }
4241
Willy Tarreauef6494c2010-01-28 17:12:36 +01004242 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004243 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4244 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4245 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004246 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004247 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004248 goto out;
4249 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004250 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004251 else if (*(args[myidx])) {
4252 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4253 file, linenum, args[0], args[myidx]);
4254 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004255 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004256 goto out;
4257 }
Emeric Brun97679e72010-09-23 17:56:44 +02004258 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004259 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004260 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004261 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004262
Emeric Brunb982a3d2010-01-04 15:45:53 +01004263 rule = (struct sticking_rule *)calloc(1, sizeof(*rule));
4264 rule->cond = cond;
4265 rule->expr = expr;
4266 rule->flags = flags;
4267 rule->table.name = name ? strdup(name) : NULL;
4268 LIST_INIT(&rule->list);
4269 if (flags & STK_ON_RSP)
4270 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4271 else
4272 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4273 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004274 else if (!strcmp(args[0], "stats")) {
4275 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4276 curproxy->uri_auth = NULL; /* we must detach from the default config */
4277
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004278 if (!*args[1]) {
4279 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004280 } else if (!strcmp(args[1], "admin")) {
4281 struct stats_admin_rule *rule;
4282
4283 if (curproxy == &defproxy) {
4284 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4285 err_code |= ERR_ALERT | ERR_FATAL;
4286 goto out;
4287 }
4288
4289 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4290 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4291 err_code |= ERR_ALERT | ERR_ABORT;
4292 goto out;
4293 }
4294
4295 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4296 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4297 file, linenum, args[0], args[1]);
4298 err_code |= ERR_ALERT | ERR_FATAL;
4299 goto out;
4300 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004301 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4302 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4303 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004304 err_code |= ERR_ALERT | ERR_FATAL;
4305 goto out;
4306 }
4307
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004308 err_code |= warnif_cond_conflicts(cond,
4309 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4310 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004311
4312 rule = (struct stats_admin_rule *)calloc(1, sizeof(*rule));
4313 rule->cond = cond;
4314 LIST_INIT(&rule->list);
4315 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004316 } else if (!strcmp(args[1], "uri")) {
4317 if (*(args[2]) == 0) {
4318 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004319 err_code |= ERR_ALERT | ERR_FATAL;
4320 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004321 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4322 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004323 err_code |= ERR_ALERT | ERR_ABORT;
4324 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004325 }
4326 } else if (!strcmp(args[1], "realm")) {
4327 if (*(args[2]) == 0) {
4328 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004329 err_code |= ERR_ALERT | ERR_FATAL;
4330 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004331 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4332 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004333 err_code |= ERR_ALERT | ERR_ABORT;
4334 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004335 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004336 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004337 unsigned interval;
4338
4339 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4340 if (err) {
4341 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4342 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004343 err_code |= ERR_ALERT | ERR_FATAL;
4344 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004345 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4346 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004347 err_code |= ERR_ALERT | ERR_ABORT;
4348 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004349 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004350 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004351 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004352
4353 if (curproxy == &defproxy) {
4354 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4355 err_code |= ERR_ALERT | ERR_FATAL;
4356 goto out;
4357 }
4358
4359 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4360 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4361 err_code |= ERR_ALERT | ERR_ABORT;
4362 goto out;
4363 }
4364
Willy Tarreauff011f22011-01-06 17:51:27 +01004365 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004366 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004367 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4368 file, linenum, args[0]);
4369 err_code |= ERR_WARN;
4370 }
4371
Willy Tarreauff011f22011-01-06 17:51:27 +01004372 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004373
Willy Tarreauff011f22011-01-06 17:51:27 +01004374 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004375 err_code |= ERR_ALERT | ERR_ABORT;
4376 goto out;
4377 }
4378
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004379 err_code |= warnif_cond_conflicts(rule->cond,
4380 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4381 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004382 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004383
Willy Tarreaubaaee002006-06-26 02:48:02 +02004384 } else if (!strcmp(args[1], "auth")) {
4385 if (*(args[2]) == 0) {
4386 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004387 err_code |= ERR_ALERT | ERR_FATAL;
4388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004389 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4390 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004391 err_code |= ERR_ALERT | ERR_ABORT;
4392 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004393 }
4394 } else if (!strcmp(args[1], "scope")) {
4395 if (*(args[2]) == 0) {
4396 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004397 err_code |= ERR_ALERT | ERR_FATAL;
4398 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004399 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4400 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004401 err_code |= ERR_ALERT | ERR_ABORT;
4402 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004403 }
4404 } else if (!strcmp(args[1], "enable")) {
4405 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4406 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004407 err_code |= ERR_ALERT | ERR_ABORT;
4408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004409 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004410 } else if (!strcmp(args[1], "hide-version")) {
4411 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4412 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004413 err_code |= ERR_ALERT | ERR_ABORT;
4414 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004415 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004416 } else if (!strcmp(args[1], "show-legends")) {
4417 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4418 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4419 err_code |= ERR_ALERT | ERR_ABORT;
4420 goto out;
4421 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004422 } else if (!strcmp(args[1], "show-node")) {
4423
4424 if (*args[2]) {
4425 int i;
4426 char c;
4427
4428 for (i=0; args[2][i]; i++) {
4429 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004430 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4431 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004432 break;
4433 }
4434
4435 if (!i || args[2][i]) {
4436 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4437 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4438 file, linenum, args[0], args[1]);
4439 err_code |= ERR_ALERT | ERR_FATAL;
4440 goto out;
4441 }
4442 }
4443
4444 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4445 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4446 err_code |= ERR_ALERT | ERR_ABORT;
4447 goto out;
4448 }
4449 } else if (!strcmp(args[1], "show-desc")) {
4450 char *desc = NULL;
4451
4452 if (*args[2]) {
4453 int i, len=0;
4454 char *d;
4455
Willy Tarreau348acfe2014-04-14 15:00:39 +02004456 for (i = 2; *args[i]; i++)
4457 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004458
4459 desc = d = (char *)calloc(1, len);
4460
Willy Tarreau348acfe2014-04-14 15:00:39 +02004461 d += snprintf(d, desc + len - d, "%s", args[2]);
4462 for (i = 3; *args[i]; i++)
4463 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004464 }
4465
4466 if (!*args[2] && !global.desc)
4467 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4468 file, linenum, args[1]);
4469 else {
4470 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4471 free(desc);
4472 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4473 err_code |= ERR_ALERT | ERR_ABORT;
4474 goto out;
4475 }
4476 free(desc);
4477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004478 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004479stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004480 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 +01004481 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004482 err_code |= ERR_ALERT | ERR_FATAL;
4483 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004484 }
4485 }
4486 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004487 int optnum;
4488
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004489 if (*(args[1]) == '\0') {
4490 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4491 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004492 err_code |= ERR_ALERT | ERR_FATAL;
4493 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004494 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004495
4496 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4497 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004498 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4499 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4500 file, linenum, cfg_opts[optnum].name);
4501 err_code |= ERR_ALERT | ERR_FATAL;
4502 goto out;
4503 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004504 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4505 goto out;
4506
Willy Tarreau93893792009-07-23 13:19:11 +02004507 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4508 err_code |= ERR_WARN;
4509 goto out;
4510 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004511
Willy Tarreau3842f002009-06-14 11:39:52 +02004512 curproxy->no_options &= ~cfg_opts[optnum].val;
4513 curproxy->options &= ~cfg_opts[optnum].val;
4514
4515 switch (kwm) {
4516 case KWM_STD:
4517 curproxy->options |= cfg_opts[optnum].val;
4518 break;
4519 case KWM_NO:
4520 curproxy->no_options |= cfg_opts[optnum].val;
4521 break;
4522 case KWM_DEF: /* already cleared */
4523 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004524 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004525
Willy Tarreau93893792009-07-23 13:19:11 +02004526 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004527 }
4528 }
4529
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004530 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4531 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004532 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4533 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4534 file, linenum, cfg_opts2[optnum].name);
4535 err_code |= ERR_ALERT | ERR_FATAL;
4536 goto out;
4537 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004538 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4539 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004540 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4541 err_code |= ERR_WARN;
4542 goto out;
4543 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004544
Willy Tarreau3842f002009-06-14 11:39:52 +02004545 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4546 curproxy->options2 &= ~cfg_opts2[optnum].val;
4547
4548 switch (kwm) {
4549 case KWM_STD:
4550 curproxy->options2 |= cfg_opts2[optnum].val;
4551 break;
4552 case KWM_NO:
4553 curproxy->no_options2 |= cfg_opts2[optnum].val;
4554 break;
4555 case KWM_DEF: /* already cleared */
4556 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004557 }
Willy Tarreau93893792009-07-23 13:19:11 +02004558 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004559 }
4560 }
4561
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004562 /* HTTP options override each other. They can be cancelled using
4563 * "no option xxx" which only switches to default mode if the mode
4564 * was this one (useful for cancelling options set in defaults
4565 * sections).
4566 */
4567 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004568 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4569 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004570 if (kwm == KWM_STD) {
4571 curproxy->options &= ~PR_O_HTTP_MODE;
4572 curproxy->options |= PR_O_HTTP_PCL;
4573 goto out;
4574 }
4575 else if (kwm == KWM_NO) {
4576 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4577 curproxy->options &= ~PR_O_HTTP_MODE;
4578 goto out;
4579 }
4580 }
4581 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004582 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4583 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004584 if (kwm == KWM_STD) {
4585 curproxy->options &= ~PR_O_HTTP_MODE;
4586 curproxy->options |= PR_O_HTTP_FCL;
4587 goto out;
4588 }
4589 else if (kwm == KWM_NO) {
4590 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4591 curproxy->options &= ~PR_O_HTTP_MODE;
4592 goto out;
4593 }
4594 }
4595 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004596 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4597 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004598 if (kwm == KWM_STD) {
4599 curproxy->options &= ~PR_O_HTTP_MODE;
4600 curproxy->options |= PR_O_HTTP_SCL;
4601 goto out;
4602 }
4603 else if (kwm == KWM_NO) {
4604 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4605 curproxy->options &= ~PR_O_HTTP_MODE;
4606 goto out;
4607 }
4608 }
4609 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004610 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4611 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004612 if (kwm == KWM_STD) {
4613 curproxy->options &= ~PR_O_HTTP_MODE;
4614 curproxy->options |= PR_O_HTTP_KAL;
4615 goto out;
4616 }
4617 else if (kwm == KWM_NO) {
4618 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4619 curproxy->options &= ~PR_O_HTTP_MODE;
4620 goto out;
4621 }
4622 }
4623 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004624 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4625 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004626 if (kwm == KWM_STD) {
4627 curproxy->options &= ~PR_O_HTTP_MODE;
4628 curproxy->options |= PR_O_HTTP_TUN;
4629 goto out;
4630 }
4631 else if (kwm == KWM_NO) {
4632 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4633 curproxy->options &= ~PR_O_HTTP_MODE;
4634 goto out;
4635 }
4636 }
4637
Joseph Lynch726ab712015-05-11 23:25:34 -07004638 /* Redispatch can take an integer argument that control when the
4639 * resispatch occurs. All values are relative to the retries option.
4640 * This can be cancelled using "no option xxx".
4641 */
4642 if (strcmp(args[1], "redispatch") == 0) {
4643 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4644 err_code |= ERR_WARN;
4645 goto out;
4646 }
4647
4648 curproxy->no_options &= ~PR_O_REDISP;
4649 curproxy->options &= ~PR_O_REDISP;
4650
4651 switch (kwm) {
4652 case KWM_STD:
4653 curproxy->options |= PR_O_REDISP;
4654 curproxy->redispatch_after = -1;
4655 if(*args[2]) {
4656 curproxy->redispatch_after = atol(args[2]);
4657 }
4658 break;
4659 case KWM_NO:
4660 curproxy->no_options |= PR_O_REDISP;
4661 curproxy->redispatch_after = 0;
4662 break;
4663 case KWM_DEF: /* already cleared */
4664 break;
4665 }
4666 goto out;
4667 }
4668
Willy Tarreau3842f002009-06-14 11:39:52 +02004669 if (kwm != KWM_STD) {
4670 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004671 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004672 err_code |= ERR_ALERT | ERR_FATAL;
4673 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004674 }
4675
Emeric Brun3a058f32009-06-30 18:26:00 +02004676 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004677 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004678 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004679 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004680 if (*(args[2]) != '\0') {
4681 if (!strcmp(args[2], "clf")) {
4682 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004683 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004684 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004685 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004686 err_code |= ERR_ALERT | ERR_FATAL;
4687 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004688 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004689 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4690 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004691 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004692 if (curproxy->conf.logformat_string != default_http_log_format &&
4693 curproxy->conf.logformat_string != default_tcp_log_format &&
4694 curproxy->conf.logformat_string != clf_http_log_format)
4695 free(curproxy->conf.logformat_string);
4696 curproxy->conf.logformat_string = logformat;
4697
4698 free(curproxy->conf.lfs_file);
4699 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4700 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004701 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004702 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004703 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004704 if (curproxy->conf.logformat_string != default_http_log_format &&
4705 curproxy->conf.logformat_string != default_tcp_log_format &&
4706 curproxy->conf.logformat_string != clf_http_log_format)
4707 free(curproxy->conf.logformat_string);
4708 curproxy->conf.logformat_string = default_tcp_log_format;
4709
4710 free(curproxy->conf.lfs_file);
4711 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4712 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004713
4714 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4715 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004716 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004717 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004718 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004719 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004720 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004721
William Lallemanddf1425a2015-04-28 20:17:49 +02004722 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4723 goto out;
4724
Willy Tarreau13943ab2006-12-31 00:24:10 +01004725 if (curproxy->cap & PR_CAP_FE)
4726 curproxy->options |= PR_O_TCP_CLI_KA;
4727 if (curproxy->cap & PR_CAP_BE)
4728 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004729 }
4730 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004731 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004732 err_code |= ERR_WARN;
4733
Willy Tarreaubaaee002006-06-26 02:48:02 +02004734 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004735 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004736 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004737 curproxy->options2 &= ~PR_O2_CHK_ANY;
4738 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004739 if (!*args[2]) { /* no argument */
4740 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4741 curproxy->check_len = strlen(DEF_CHECK_REQ);
4742 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004743 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004744 curproxy->check_req = (char *)malloc(reqlen);
4745 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004746 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004747 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004748 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004749 if (*args[4])
4750 reqlen += strlen(args[4]);
4751 else
4752 reqlen += strlen("HTTP/1.0");
4753
4754 curproxy->check_req = (char *)malloc(reqlen);
4755 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004756 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004757 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004758 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4759 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004760 }
4761 else if (!strcmp(args[1], "ssl-hello-chk")) {
4762 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004763 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004764 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004765
Willy Tarreaua534fea2008-08-03 12:19:50 +02004766 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004767 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004768 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004769 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004770
4771 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4772 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004773 }
Willy Tarreau23677902007-05-08 23:50:35 +02004774 else if (!strcmp(args[1], "smtpchk")) {
4775 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004776 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004777 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004778 curproxy->options2 &= ~PR_O2_CHK_ANY;
4779 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004780
4781 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4782 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4783 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4784 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4785 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4786 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
4787 curproxy->check_req = (char *)malloc(reqlen);
4788 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4789 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4790 } else {
4791 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4792 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4793 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4794 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4795 }
4796 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004797 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4798 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004799 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004800 else if (!strcmp(args[1], "pgsql-check")) {
4801 /* use PostgreSQL request to check servers' health */
4802 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4803 err_code |= ERR_WARN;
4804
4805 free(curproxy->check_req);
4806 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004807 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004808 curproxy->options2 |= PR_O2_PGSQL_CHK;
4809
4810 if (*(args[2])) {
4811 int cur_arg = 2;
4812
4813 while (*(args[cur_arg])) {
4814 if (strcmp(args[cur_arg], "user") == 0) {
4815 char * packet;
4816 uint32_t packet_len;
4817 uint32_t pv;
4818
4819 /* suboption header - needs additional argument for it */
4820 if (*(args[cur_arg+1]) == 0) {
4821 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4822 file, linenum, args[0], args[1], args[cur_arg]);
4823 err_code |= ERR_ALERT | ERR_FATAL;
4824 goto out;
4825 }
4826
4827 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4828 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4829 pv = htonl(0x30000); /* protocol version 3.0 */
4830
4831 packet = (char*) calloc(1, packet_len);
4832
4833 memcpy(packet + 4, &pv, 4);
4834
4835 /* copy "user" */
4836 memcpy(packet + 8, "user", 4);
4837
4838 /* copy username */
4839 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4840
4841 free(curproxy->check_req);
4842 curproxy->check_req = packet;
4843 curproxy->check_len = packet_len;
4844
4845 packet_len = htonl(packet_len);
4846 memcpy(packet, &packet_len, 4);
4847 cur_arg += 2;
4848 } else {
4849 /* unknown suboption - catchall */
4850 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4851 file, linenum, args[0], args[1]);
4852 err_code |= ERR_ALERT | ERR_FATAL;
4853 goto out;
4854 }
4855 } /* end while loop */
4856 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004857 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4858 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004859 }
4860
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004861 else if (!strcmp(args[1], "redis-check")) {
4862 /* use REDIS PING request to check servers' health */
4863 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4864 err_code |= ERR_WARN;
4865
4866 free(curproxy->check_req);
4867 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004868 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004869 curproxy->options2 |= PR_O2_REDIS_CHK;
4870
4871 curproxy->check_req = (char *) malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
4872 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4873 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004874
4875 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4876 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004877 }
4878
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004879 else if (!strcmp(args[1], "mysql-check")) {
4880 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004881 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4882 err_code |= ERR_WARN;
4883
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004884 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004885 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004886 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004887 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004888
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004889 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004890 * const char mysql40_client_auth_pkt[] = {
4891 * "\x0e\x00\x00" // packet length
4892 * "\x01" // packet number
4893 * "\x00\x00" // client capabilities
4894 * "\x00\x00\x01" // max packet
4895 * "haproxy\x00" // username (null terminated string)
4896 * "\x00" // filler (always 0x00)
4897 * "\x01\x00\x00" // packet length
4898 * "\x00" // packet number
4899 * "\x01" // COM_QUIT command
4900 * };
4901 */
4902
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004903 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4904 * const char mysql41_client_auth_pkt[] = {
4905 * "\x0e\x00\x00\" // packet length
4906 * "\x01" // packet number
4907 * "\x00\x00\x00\x00" // client capabilities
4908 * "\x00\x00\x00\x01" // max packet
4909 * "\x21" // character set (UTF-8)
4910 * char[23] // All zeroes
4911 * "haproxy\x00" // username (null terminated string)
4912 * "\x00" // filler (always 0x00)
4913 * "\x01\x00\x00" // packet length
4914 * "\x00" // packet number
4915 * "\x01" // COM_QUIT command
4916 * };
4917 */
4918
4919
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004920 if (*(args[2])) {
4921 int cur_arg = 2;
4922
4923 while (*(args[cur_arg])) {
4924 if (strcmp(args[cur_arg], "user") == 0) {
4925 char *mysqluser;
4926 int packetlen, reqlen, userlen;
4927
4928 /* suboption header - needs additional argument for it */
4929 if (*(args[cur_arg+1]) == 0) {
4930 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4931 file, linenum, args[0], args[1], args[cur_arg]);
4932 err_code |= ERR_ALERT | ERR_FATAL;
4933 goto out;
4934 }
4935 mysqluser = args[cur_arg + 1];
4936 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004937
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004938 if (*(args[cur_arg+2])) {
4939 if (!strcmp(args[cur_arg+2], "post-41")) {
4940 packetlen = userlen + 7 + 27;
4941 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004942
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004943 free(curproxy->check_req);
4944 curproxy->check_req = (char *)calloc(1, reqlen);
4945 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004946
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004947 snprintf(curproxy->check_req, 4, "%c%c%c",
4948 ((unsigned char) packetlen & 0xff),
4949 ((unsigned char) (packetlen >> 8) & 0xff),
4950 ((unsigned char) (packetlen >> 16) & 0xff));
4951
4952 curproxy->check_req[3] = 1;
4953 curproxy->check_req[5] = 130;
4954 curproxy->check_req[11] = 1;
4955 curproxy->check_req[12] = 33;
4956 memcpy(&curproxy->check_req[36], mysqluser, userlen);
4957 curproxy->check_req[36 + userlen + 1 + 1] = 1;
4958 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
4959 cur_arg += 3;
4960 } else {
4961 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
4962 err_code |= ERR_ALERT | ERR_FATAL;
4963 goto out;
4964 }
4965 } else {
4966 packetlen = userlen + 7;
4967 reqlen = packetlen + 9;
4968
4969 free(curproxy->check_req);
4970 curproxy->check_req = (char *)calloc(1, reqlen);
4971 curproxy->check_len = reqlen;
4972
4973 snprintf(curproxy->check_req, 4, "%c%c%c",
4974 ((unsigned char) packetlen & 0xff),
4975 ((unsigned char) (packetlen >> 8) & 0xff),
4976 ((unsigned char) (packetlen >> 16) & 0xff));
4977
4978 curproxy->check_req[3] = 1;
4979 curproxy->check_req[5] = 128;
4980 curproxy->check_req[8] = 1;
4981 memcpy(&curproxy->check_req[9], mysqluser, userlen);
4982 curproxy->check_req[9 + userlen + 1 + 1] = 1;
4983 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
4984 cur_arg += 2;
4985 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004986 } else {
4987 /* unknown suboption - catchall */
4988 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4989 file, linenum, args[0], args[1]);
4990 err_code |= ERR_ALERT | ERR_FATAL;
4991 goto out;
4992 }
4993 } /* end while loop */
4994 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004995 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02004996 else if (!strcmp(args[1], "ldap-check")) {
4997 /* use LDAP request to check servers' health */
4998 free(curproxy->check_req);
4999 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005000 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005001 curproxy->options2 |= PR_O2_LDAP_CHK;
5002
5003 curproxy->check_req = (char *) malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
5004 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5005 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005006 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5007 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005008 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005009 else if (!strcmp(args[1], "tcp-check")) {
5010 /* use raw TCPCHK send/expect to check servers' health */
5011 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5012 err_code |= ERR_WARN;
5013
5014 free(curproxy->check_req);
5015 curproxy->check_req = NULL;
5016 curproxy->options2 &= ~PR_O2_CHK_ANY;
5017 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005018 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5019 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005020 }
Simon Horman98637e52014-06-20 12:30:16 +09005021 else if (!strcmp(args[1], "external-check")) {
5022 /* excute an external command to check servers' health */
5023 free(curproxy->check_req);
5024 curproxy->check_req = NULL;
5025 curproxy->options2 &= ~PR_O2_CHK_ANY;
5026 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005027 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5028 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005029 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005030 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005031 int cur_arg;
5032
5033 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5034 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005035 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005036
Willy Tarreau87cf5142011-08-19 22:57:24 +02005037 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005038
5039 free(curproxy->fwdfor_hdr_name);
5040 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5041 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5042
5043 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5044 cur_arg = 2;
5045 while (*(args[cur_arg])) {
5046 if (!strcmp(args[cur_arg], "except")) {
5047 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005048 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005049 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5050 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005051 err_code |= ERR_ALERT | ERR_FATAL;
5052 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005053 }
5054 /* flush useless bits */
5055 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005056 cur_arg += 2;
5057 } else if (!strcmp(args[cur_arg], "header")) {
5058 /* suboption header - needs additional argument for it */
5059 if (*(args[cur_arg+1]) == 0) {
5060 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5061 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005062 err_code |= ERR_ALERT | ERR_FATAL;
5063 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005064 }
5065 free(curproxy->fwdfor_hdr_name);
5066 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5067 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5068 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005069 } else if (!strcmp(args[cur_arg], "if-none")) {
5070 curproxy->options &= ~PR_O_FF_ALWAYS;
5071 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005072 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005073 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005074 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005075 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005076 err_code |= ERR_ALERT | ERR_FATAL;
5077 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005078 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005079 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005080 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005081 else if (!strcmp(args[1], "originalto")) {
5082 int cur_arg;
5083
5084 /* insert x-original-to field, but not for the IP address listed as an except.
5085 * set default options (ie: bitfield, header name, etc)
5086 */
5087
5088 curproxy->options |= PR_O_ORGTO;
5089
5090 free(curproxy->orgto_hdr_name);
5091 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5092 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5093
Willy Tarreau87cf5142011-08-19 22:57:24 +02005094 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005095 cur_arg = 2;
5096 while (*(args[cur_arg])) {
5097 if (!strcmp(args[cur_arg], "except")) {
5098 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005099 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 +02005100 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5101 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005102 err_code |= ERR_ALERT | ERR_FATAL;
5103 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005104 }
5105 /* flush useless bits */
5106 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5107 cur_arg += 2;
5108 } else if (!strcmp(args[cur_arg], "header")) {
5109 /* suboption header - needs additional argument for it */
5110 if (*(args[cur_arg+1]) == 0) {
5111 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5112 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005113 err_code |= ERR_ALERT | ERR_FATAL;
5114 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005115 }
5116 free(curproxy->orgto_hdr_name);
5117 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5118 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5119 cur_arg += 2;
5120 } else {
5121 /* unknown suboption - catchall */
5122 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5123 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005124 err_code |= ERR_ALERT | ERR_FATAL;
5125 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005126 }
5127 } /* end while loop */
5128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005129 else {
5130 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005131 err_code |= ERR_ALERT | ERR_FATAL;
5132 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005133 }
Willy Tarreau93893792009-07-23 13:19:11 +02005134 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005135 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005136 else if (!strcmp(args[0], "default_backend")) {
5137 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005138 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005139
5140 if (*(args[1]) == 0) {
5141 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005142 err_code |= ERR_ALERT | ERR_FATAL;
5143 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005144 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005145 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005146 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005147
5148 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5149 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005150 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005151 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005152 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005153 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005154
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005155 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5156 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 +01005157 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005158 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005159 /* enable reconnections to dispatch */
5160 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005161
5162 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5163 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005164 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005165 else if (!strcmp(args[0], "http-reuse")) {
5166 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5167 err_code |= ERR_WARN;
5168
5169 if (strcmp(args[1], "never") == 0) {
5170 /* enable a graceful server shutdown on an HTTP 404 response */
5171 curproxy->options &= ~PR_O_REUSE_MASK;
5172 curproxy->options |= PR_O_REUSE_NEVR;
5173 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5174 goto out;
5175 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005176 else if (strcmp(args[1], "safe") == 0) {
5177 /* enable a graceful server shutdown on an HTTP 404 response */
5178 curproxy->options &= ~PR_O_REUSE_MASK;
5179 curproxy->options |= PR_O_REUSE_SAFE;
5180 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5181 goto out;
5182 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005183 else if (strcmp(args[1], "aggressive") == 0) {
5184 curproxy->options &= ~PR_O_REUSE_MASK;
5185 curproxy->options |= PR_O_REUSE_AGGR;
5186 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5187 goto out;
5188 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005189 else if (strcmp(args[1], "always") == 0) {
5190 /* enable a graceful server shutdown on an HTTP 404 response */
5191 curproxy->options &= ~PR_O_REUSE_MASK;
5192 curproxy->options |= PR_O_REUSE_ALWS;
5193 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5194 goto out;
5195 }
5196 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005197 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005198 err_code |= ERR_ALERT | ERR_FATAL;
5199 goto out;
5200 }
5201 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005202 else if (!strcmp(args[0], "http-check")) {
5203 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005204 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005205
5206 if (strcmp(args[1], "disable-on-404") == 0) {
5207 /* enable a graceful server shutdown on an HTTP 404 response */
5208 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005209 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5210 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005211 }
Willy Tarreauef781042010-01-27 11:53:01 +01005212 else if (strcmp(args[1], "send-state") == 0) {
5213 /* enable emission of the apparent state of a server in HTTP checks */
5214 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005215 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5216 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005217 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005218 else if (strcmp(args[1], "expect") == 0) {
5219 const char *ptr_arg;
5220 int cur_arg;
5221
5222 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5223 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
5226 }
5227
5228 cur_arg = 2;
5229 /* consider exclamation marks, sole or at the beginning of a word */
5230 while (*(ptr_arg = args[cur_arg])) {
5231 while (*ptr_arg == '!') {
5232 curproxy->options2 ^= PR_O2_EXP_INV;
5233 ptr_arg++;
5234 }
5235 if (*ptr_arg)
5236 break;
5237 cur_arg++;
5238 }
5239 /* now ptr_arg points to the beginning of a word past any possible
5240 * exclamation mark, and cur_arg is the argument which holds this word.
5241 */
5242 if (strcmp(ptr_arg, "status") == 0) {
5243 if (!*(args[cur_arg + 1])) {
5244 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5245 file, linenum, args[0], args[1], ptr_arg);
5246 err_code |= ERR_ALERT | ERR_FATAL;
5247 goto out;
5248 }
5249 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005250 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005251 curproxy->expect_str = strdup(args[cur_arg + 1]);
5252 }
5253 else if (strcmp(ptr_arg, "string") == 0) {
5254 if (!*(args[cur_arg + 1])) {
5255 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5256 file, linenum, args[0], args[1], ptr_arg);
5257 err_code |= ERR_ALERT | ERR_FATAL;
5258 goto out;
5259 }
5260 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005261 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005262 curproxy->expect_str = strdup(args[cur_arg + 1]);
5263 }
5264 else if (strcmp(ptr_arg, "rstatus") == 0) {
5265 if (!*(args[cur_arg + 1])) {
5266 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5267 file, linenum, args[0], args[1], ptr_arg);
5268 err_code |= ERR_ALERT | ERR_FATAL;
5269 goto out;
5270 }
5271 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005272 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005273 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005274 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005275 free(curproxy->expect_regex);
5276 curproxy->expect_regex = NULL;
5277 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005278 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005279 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5280 error = NULL;
5281 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5282 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5283 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5284 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005285 err_code |= ERR_ALERT | ERR_FATAL;
5286 goto out;
5287 }
5288 }
5289 else if (strcmp(ptr_arg, "rstring") == 0) {
5290 if (!*(args[cur_arg + 1])) {
5291 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5292 file, linenum, args[0], args[1], ptr_arg);
5293 err_code |= ERR_ALERT | ERR_FATAL;
5294 goto out;
5295 }
5296 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005297 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005298 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005299 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005300 free(curproxy->expect_regex);
5301 curproxy->expect_regex = NULL;
5302 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005303 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005304 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5305 error = NULL;
5306 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5307 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5308 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5309 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005310 err_code |= ERR_ALERT | ERR_FATAL;
5311 goto out;
5312 }
5313 }
5314 else {
5315 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5316 file, linenum, args[0], args[1], ptr_arg);
5317 err_code |= ERR_ALERT | ERR_FATAL;
5318 goto out;
5319 }
5320 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005321 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005322 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 +02005323 err_code |= ERR_ALERT | ERR_FATAL;
5324 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005325 }
5326 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005327 else if (!strcmp(args[0], "tcp-check")) {
5328 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5329 err_code |= ERR_WARN;
5330
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005331 if (strcmp(args[1], "comment") == 0) {
5332 int cur_arg;
5333 struct tcpcheck_rule *tcpcheck;
5334
5335 cur_arg = 1;
5336 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5337 tcpcheck->action = TCPCHK_ACT_COMMENT;
5338
5339 if (!*args[cur_arg + 1]) {
5340 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5341 file, linenum, args[cur_arg]);
5342 err_code |= ERR_ALERT | ERR_FATAL;
5343 goto out;
5344 }
5345
5346 tcpcheck->comment = strdup(args[cur_arg + 1]);
5347
5348 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005349 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5350 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005351 }
5352 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005353 const char *ptr_arg;
5354 int cur_arg;
5355 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005356
5357 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005358 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5359 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5360 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5361 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5362 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005363
Willy Tarreau5581c272015-05-13 12:24:53 +02005364 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5365 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5366 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5367 file, linenum);
5368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005370 }
5371
5372 cur_arg = 2;
5373 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5374 tcpcheck->action = TCPCHK_ACT_CONNECT;
5375
5376 /* parsing each parameters to fill up the rule */
5377 while (*(ptr_arg = args[cur_arg])) {
5378 /* tcp port */
5379 if (strcmp(args[cur_arg], "port") == 0) {
5380 if ( (atol(args[cur_arg + 1]) > 65535) ||
5381 (atol(args[cur_arg + 1]) < 1) ){
5382 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5383 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5384 err_code |= ERR_ALERT | ERR_FATAL;
5385 goto out;
5386 }
5387 tcpcheck->port = atol(args[cur_arg + 1]);
5388 cur_arg += 2;
5389 }
5390 /* send proxy protocol */
5391 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5392 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5393 cur_arg++;
5394 }
5395#ifdef USE_OPENSSL
5396 else if (strcmp(args[cur_arg], "ssl") == 0) {
5397 curproxy->options |= PR_O_TCPCHK_SSL;
5398 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5399 cur_arg++;
5400 }
5401#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005402 /* comment for this tcpcheck line */
5403 else if (strcmp(args[cur_arg], "comment") == 0) {
5404 if (!*args[cur_arg + 1]) {
5405 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5406 file, linenum, args[cur_arg]);
5407 err_code |= ERR_ALERT | ERR_FATAL;
5408 goto out;
5409 }
5410 tcpcheck->comment = strdup(args[cur_arg + 1]);
5411 cur_arg += 2;
5412 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005413 else {
5414#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005415 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 +01005416#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005417 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 +01005418#endif /* USE_OPENSSL */
5419 file, linenum, args[0], args[1], args[cur_arg]);
5420 err_code |= ERR_ALERT | ERR_FATAL;
5421 goto out;
5422 }
5423
5424 }
5425
5426 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5427 }
5428 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005429 if (! *(args[2]) ) {
5430 /* SEND string expected */
5431 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5432 file, linenum, args[0], args[1], args[2]);
5433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
5435 } else {
5436 struct tcpcheck_rule *tcpcheck;
5437
5438 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5439
5440 tcpcheck->action = TCPCHK_ACT_SEND;
5441 tcpcheck->string_len = strlen(args[2]);
5442 tcpcheck->string = strdup(args[2]);
5443 tcpcheck->expect_regex = NULL;
5444
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005445 /* comment for this tcpcheck line */
5446 if (strcmp(args[3], "comment") == 0) {
5447 if (!*args[4]) {
5448 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5449 file, linenum, args[3]);
5450 err_code |= ERR_ALERT | ERR_FATAL;
5451 goto out;
5452 }
5453 tcpcheck->comment = strdup(args[4]);
5454 }
5455
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005456 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5457 }
5458 }
5459 else if (strcmp(args[1], "send-binary") == 0) {
5460 if (! *(args[2]) ) {
5461 /* SEND binary string expected */
5462 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5463 file, linenum, args[0], args[1], args[2]);
5464 err_code |= ERR_ALERT | ERR_FATAL;
5465 goto out;
5466 } else {
5467 struct tcpcheck_rule *tcpcheck;
5468 char *err = NULL;
5469
5470 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5471
5472 tcpcheck->action = TCPCHK_ACT_SEND;
5473 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5474 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5475 file, linenum, args[0], args[1], args[2], err);
5476 err_code |= ERR_ALERT | ERR_FATAL;
5477 goto out;
5478 }
5479 tcpcheck->expect_regex = NULL;
5480
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005481 /* comment for this tcpcheck line */
5482 if (strcmp(args[3], "comment") == 0) {
5483 if (!*args[4]) {
5484 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5485 file, linenum, args[3]);
5486 err_code |= ERR_ALERT | ERR_FATAL;
5487 goto out;
5488 }
5489 tcpcheck->comment = strdup(args[4]);
5490 }
5491
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005492 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5493 }
5494 }
5495 else if (strcmp(args[1], "expect") == 0) {
5496 const char *ptr_arg;
5497 int cur_arg;
5498 int inverse = 0;
5499
5500 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5501 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5502 err_code |= ERR_ALERT | ERR_FATAL;
5503 goto out;
5504 }
5505
5506 cur_arg = 2;
5507 /* consider exclamation marks, sole or at the beginning of a word */
5508 while (*(ptr_arg = args[cur_arg])) {
5509 while (*ptr_arg == '!') {
5510 inverse = !inverse;
5511 ptr_arg++;
5512 }
5513 if (*ptr_arg)
5514 break;
5515 cur_arg++;
5516 }
5517 /* now ptr_arg points to the beginning of a word past any possible
5518 * exclamation mark, and cur_arg is the argument which holds this word.
5519 */
5520 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005521 struct tcpcheck_rule *tcpcheck;
5522 char *err = NULL;
5523
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005524 if (!*(args[cur_arg + 1])) {
5525 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5526 file, linenum, args[0], args[1], ptr_arg);
5527 err_code |= ERR_ALERT | ERR_FATAL;
5528 goto out;
5529 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005530
5531 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5532
5533 tcpcheck->action = TCPCHK_ACT_EXPECT;
5534 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5535 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5536 file, linenum, args[0], args[1], args[2], err);
5537 err_code |= ERR_ALERT | ERR_FATAL;
5538 goto out;
5539 }
5540 tcpcheck->expect_regex = NULL;
5541 tcpcheck->inverse = inverse;
5542
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005543 /* tcpcheck comment */
5544 cur_arg += 2;
5545 if (strcmp(args[cur_arg], "comment") == 0) {
5546 if (!*args[cur_arg + 1]) {
5547 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5548 file, linenum, args[cur_arg + 1]);
5549 err_code |= ERR_ALERT | ERR_FATAL;
5550 goto out;
5551 }
5552 tcpcheck->comment = strdup(args[cur_arg + 1]);
5553 }
5554
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005555 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5556 }
5557 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005558 struct tcpcheck_rule *tcpcheck;
5559
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005560 if (!*(args[cur_arg + 1])) {
5561 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5562 file, linenum, args[0], args[1], ptr_arg);
5563 err_code |= ERR_ALERT | ERR_FATAL;
5564 goto out;
5565 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005566
5567 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5568
5569 tcpcheck->action = TCPCHK_ACT_EXPECT;
5570 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5571 tcpcheck->string = strdup(args[cur_arg + 1]);
5572 tcpcheck->expect_regex = NULL;
5573 tcpcheck->inverse = inverse;
5574
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005575 /* tcpcheck comment */
5576 cur_arg += 2;
5577 if (strcmp(args[cur_arg], "comment") == 0) {
5578 if (!*args[cur_arg + 1]) {
5579 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5580 file, linenum, args[cur_arg + 1]);
5581 err_code |= ERR_ALERT | ERR_FATAL;
5582 goto out;
5583 }
5584 tcpcheck->comment = strdup(args[cur_arg + 1]);
5585 }
5586
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005587 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5588 }
5589 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005590 struct tcpcheck_rule *tcpcheck;
5591
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005592 if (!*(args[cur_arg + 1])) {
5593 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5594 file, linenum, args[0], args[1], ptr_arg);
5595 err_code |= ERR_ALERT | ERR_FATAL;
5596 goto out;
5597 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005598
5599 tcpcheck = (struct tcpcheck_rule *)calloc(1, sizeof(*tcpcheck));
5600
5601 tcpcheck->action = TCPCHK_ACT_EXPECT;
5602 tcpcheck->string_len = 0;
5603 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005604 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5605 error = NULL;
5606 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5607 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5608 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5609 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005610 err_code |= ERR_ALERT | ERR_FATAL;
5611 goto out;
5612 }
5613 tcpcheck->inverse = inverse;
5614
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005615 /* tcpcheck comment */
5616 cur_arg += 2;
5617 if (strcmp(args[cur_arg], "comment") == 0) {
5618 if (!*args[cur_arg + 1]) {
5619 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5620 file, linenum, args[cur_arg + 1]);
5621 err_code |= ERR_ALERT | ERR_FATAL;
5622 goto out;
5623 }
5624 tcpcheck->comment = strdup(args[cur_arg + 1]);
5625 }
5626
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005627 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5628 }
5629 else {
5630 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5631 file, linenum, args[0], args[1], ptr_arg);
5632 err_code |= ERR_ALERT | ERR_FATAL;
5633 goto out;
5634 }
5635 }
5636 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005637 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
5640 }
5641 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005642 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005643 if (curproxy == &defproxy) {
5644 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005645 err_code |= ERR_ALERT | ERR_FATAL;
5646 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005647 }
5648
Willy Tarreaub80c2302007-11-30 20:51:32 +01005649 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005650 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005651
5652 if (strcmp(args[1], "fail") == 0) {
5653 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005654 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005655 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5656 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005657 err_code |= ERR_ALERT | ERR_FATAL;
5658 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005659 }
5660
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005661 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5662 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5663 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005664 err_code |= ERR_ALERT | ERR_FATAL;
5665 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005666 }
5667 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5668 }
5669 else {
5670 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005671 err_code |= ERR_ALERT | ERR_FATAL;
5672 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005673 }
5674 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005675#ifdef TPROXY
5676 else if (!strcmp(args[0], "transparent")) {
5677 /* enable transparent proxy connections */
5678 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005679 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5680 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005681 }
5682#endif
5683 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005684 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005685 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005686
Willy Tarreaubaaee002006-06-26 02:48:02 +02005687 if (*(args[1]) == 0) {
5688 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005689 err_code |= ERR_ALERT | ERR_FATAL;
5690 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005691 }
5692 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005693 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5694 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005695 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005696 else if (!strcmp(args[0], "backlog")) { /* backlog */
5697 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005698 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005699
5700 if (*(args[1]) == 0) {
5701 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005702 err_code |= ERR_ALERT | ERR_FATAL;
5703 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005704 }
5705 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005706 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5707 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005708 }
Willy Tarreau86034312006-12-29 00:10:33 +01005709 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005710 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005711 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005712
Willy Tarreau86034312006-12-29 00:10:33 +01005713 if (*(args[1]) == 0) {
5714 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_ALERT | ERR_FATAL;
5716 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005717 }
5718 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5720 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005721 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005722 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5723 if (*(args[1]) == 0) {
5724 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005725 err_code |= ERR_ALERT | ERR_FATAL;
5726 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005727 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005728 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5729 if (err) {
5730 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5731 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005732 err_code |= ERR_ALERT | ERR_FATAL;
5733 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005734 }
5735 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005736 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5737 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005738 }
5739 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005740 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005741 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005742 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005743
Willy Tarreaubaaee002006-06-26 02:48:02 +02005744 if (curproxy == &defproxy) {
5745 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005746 err_code |= ERR_ALERT | ERR_FATAL;
5747 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005748 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005749 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005751
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005752 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005753 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005754 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005755 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005756 goto out;
5757 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005758
5759 proto = protocol_by_family(sk->ss_family);
5760 if (!proto || !proto->connect) {
5761 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5762 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005763 err_code |= ERR_ALERT | ERR_FATAL;
5764 goto out;
5765 }
5766
5767 if (port1 != port2) {
5768 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5769 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005770 err_code |= ERR_ALERT | ERR_FATAL;
5771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005772 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005773
5774 if (!port1) {
5775 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5776 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005777 err_code |= ERR_ALERT | ERR_FATAL;
5778 goto out;
5779 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005780
William Lallemanddf1425a2015-04-28 20:17:49 +02005781 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5782 goto out;
5783
Willy Tarreaud5191e72010-02-09 20:50:45 +01005784 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005785 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786 }
5787 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005788 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005789 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005790
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005791 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5792 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005793 err_code |= ERR_ALERT | ERR_FATAL;
5794 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005795 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005796 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005797 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005798 /**
5799 * The syntax for hash-type config element is
5800 * hash-type {map-based|consistent} [[<algo>] avalanche]
5801 *
5802 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5803 */
5804 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005805
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005806 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5807 err_code |= ERR_WARN;
5808
5809 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005810 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5811 }
5812 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005813 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5814 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005815 else if (strcmp(args[1], "avalanche") == 0) {
5816 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]);
5817 err_code |= ERR_ALERT | ERR_FATAL;
5818 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005819 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005820 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005821 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005822 err_code |= ERR_ALERT | ERR_FATAL;
5823 goto out;
5824 }
Bhaskar98634f02013-10-29 23:30:51 -04005825
5826 /* set the hash function to use */
5827 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005828 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005829 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005830
5831 /* if consistent with no argument, then avalanche modifier is also applied */
5832 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5833 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005834 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005835 /* set the hash function */
5836 if (!strcmp(args[2], "sdbm")) {
5837 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5838 }
5839 else if (!strcmp(args[2], "djb2")) {
5840 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005841 }
5842 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005843 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005844 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005845 else if (!strcmp(args[2], "crc32")) {
5846 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5847 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005848 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005849 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 -05005850 err_code |= ERR_ALERT | ERR_FATAL;
5851 goto out;
5852 }
5853
5854 /* set the hash modifier */
5855 if (!strcmp(args[3], "avalanche")) {
5856 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5857 }
5858 else if (*args[3]) {
5859 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5860 err_code |= ERR_ALERT | ERR_FATAL;
5861 goto out;
5862 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005863 }
William Lallemanda73203e2012-03-12 12:48:57 +01005864 }
William Lallemanda73203e2012-03-12 12:48:57 +01005865 else if (strcmp(args[0], "unique-id-format") == 0) {
5866 if (!*(args[1])) {
5867 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5868 err_code |= ERR_ALERT | ERR_FATAL;
5869 goto out;
5870 }
William Lallemand3203ff42012-11-11 17:30:56 +01005871 if (*(args[2])) {
5872 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5873 err_code |= ERR_ALERT | ERR_FATAL;
5874 goto out;
5875 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005876 free(curproxy->conf.uniqueid_format_string);
5877 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005878
Willy Tarreau62a61232013-04-12 18:13:46 +02005879 free(curproxy->conf.uif_file);
5880 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5881 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005882 }
William Lallemanda73203e2012-03-12 12:48:57 +01005883
5884 else if (strcmp(args[0], "unique-id-header") == 0) {
5885 if (!*(args[1])) {
5886 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5887 err_code |= ERR_ALERT | ERR_FATAL;
5888 goto out;
5889 }
5890 free(curproxy->header_unique_id);
5891 curproxy->header_unique_id = strdup(args[1]);
5892 }
5893
William Lallemand723b73a2012-02-08 16:37:49 +01005894 else if (strcmp(args[0], "log-format") == 0) {
5895 if (!*(args[1])) {
5896 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5897 err_code |= ERR_ALERT | ERR_FATAL;
5898 goto out;
5899 }
William Lallemand3203ff42012-11-11 17:30:56 +01005900 if (*(args[2])) {
5901 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5902 err_code |= ERR_ALERT | ERR_FATAL;
5903 goto out;
5904 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005905
Willy Tarreau62a61232013-04-12 18:13:46 +02005906 if (curproxy->conf.logformat_string != default_http_log_format &&
5907 curproxy->conf.logformat_string != default_tcp_log_format &&
5908 curproxy->conf.logformat_string != clf_http_log_format)
5909 free(curproxy->conf.logformat_string);
5910 curproxy->conf.logformat_string = strdup(args[1]);
5911
5912 free(curproxy->conf.lfs_file);
5913 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5914 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005915
5916 /* get a chance to improve log-format error reporting by
5917 * reporting the correct line-number when possible.
5918 */
5919 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5920 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5921 file, linenum, curproxy->id);
5922 err_code |= ERR_WARN;
5923 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005924 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005925 else if (!strcmp(args[0], "log-format-sd")) {
5926 if (!*(args[1])) {
5927 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
5930 }
5931 if (*(args[2])) {
5932 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
5936
5937 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
5938 free(curproxy->conf.logformat_sd_string);
5939 curproxy->conf.logformat_sd_string = strdup(args[1]);
5940
5941 free(curproxy->conf.lfsd_file);
5942 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
5943 curproxy->conf.lfsd_line = curproxy->conf.args.line;
5944
5945 /* get a chance to improve log-format-sd error reporting by
5946 * reporting the correct line-number when possible.
5947 */
5948 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5949 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
5950 file, linenum, curproxy->id);
5951 err_code |= ERR_WARN;
5952 }
5953 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01005954 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
5955 if (*(args[1]) == 0) {
5956 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
5957 err_code |= ERR_ALERT | ERR_FATAL;
5958 goto out;
5959 }
Dragan Dosen43885c72015-10-01 13:18:13 +02005960 chunk_destroy(&curproxy->log_tag);
5961 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01005962 }
William Lallemand0f99e342011-10-12 17:50:54 +02005963 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
5964 /* delete previous herited or defined syslog servers */
5965 struct logsrv *back;
5966
5967 if (*(args[1]) != 0) {
5968 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
5969 err_code |= ERR_ALERT | ERR_FATAL;
5970 goto out;
5971 }
5972
William Lallemand723b73a2012-02-08 16:37:49 +01005973 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
5974 LIST_DEL(&tmplogsrv->list);
5975 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02005976 }
5977 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005978 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02005979 struct logsrv *logsrv;
5980
Willy Tarreaubaaee002006-06-26 02:48:02 +02005981 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02005982 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01005983 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
William Lallemand0f99e342011-10-12 17:50:54 +02005984 struct logsrv *node = malloc(sizeof(struct logsrv));
William Lallemand723b73a2012-02-08 16:37:49 +01005985 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02005986 LIST_INIT(&node->list);
5987 LIST_ADDQ(&curproxy->logsrvs, &node->list);
5988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 }
5990 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01005991 struct sockaddr_storage *sk;
5992 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02005993 int arg = 0;
5994 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02005995
5996 logsrv = calloc(1, sizeof(struct logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02005997
Willy Tarreau18324f52014-06-27 18:10:07 +02005998 /* just after the address, a length may be specified */
5999 if (strcmp(args[arg+2], "len") == 0) {
6000 len = atoi(args[arg+3]);
6001 if (len < 80 || len > 65535) {
6002 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6003 file, linenum, args[arg+3]);
6004 err_code |= ERR_ALERT | ERR_FATAL;
6005 goto out;
6006 }
6007 logsrv->maxlen = len;
6008
6009 /* skip these two args */
6010 arg += 2;
6011 }
6012 else
6013 logsrv->maxlen = MAX_SYSLOG_LEN;
6014
6015 if (logsrv->maxlen > global.max_syslog_len) {
6016 global.max_syslog_len = logsrv->maxlen;
Dragan Dosen59cee972015-09-19 22:09:02 +02006017 logheader = realloc(logheader, global.max_syslog_len + 1);
Dragan Dosen1322d092015-09-22 16:05:32 +02006018 logheader_rfc5424 = realloc(logheader_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006019 logline = realloc(logline, global.max_syslog_len + 1);
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006020 logline_rfc5424 = realloc(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006021 }
6022
Dragan Dosen1322d092015-09-22 16:05:32 +02006023 /* after the length, a format may be specified */
6024 if (strcmp(args[arg+2], "format") == 0) {
6025 logsrv->format = get_log_format(args[arg+3]);
6026 if (logsrv->format < 0) {
6027 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6028 err_code |= ERR_ALERT | ERR_FATAL;
6029 goto out;
6030 }
6031
6032 /* skip these two args */
6033 arg += 2;
6034 }
6035
William Lallemanddf1425a2015-04-28 20:17:49 +02006036 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6037 goto out;
6038
Willy Tarreau18324f52014-06-27 18:10:07 +02006039 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006040 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006041 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006042 err_code |= ERR_ALERT | ERR_FATAL;
6043 goto out;
6044
Willy Tarreaubaaee002006-06-26 02:48:02 +02006045 }
6046
William Lallemand0f99e342011-10-12 17:50:54 +02006047 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006048 if (*(args[arg+3])) {
6049 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006050 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006051 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
6054
Willy Tarreaubaaee002006-06-26 02:48:02 +02006055 }
6056 }
6057
William Lallemand0f99e342011-10-12 17:50:54 +02006058 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006059 if (*(args[arg+4])) {
6060 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006061 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006062 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006063 err_code |= ERR_ALERT | ERR_FATAL;
6064 goto out;
6065
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006066 }
6067 }
6068
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006069 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006070 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006071 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006072 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006073 goto out;
6074 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006075
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006076 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006077
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006078 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006079 if (port1 != port2) {
6080 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6081 file, linenum, args[0], args[1]);
6082 err_code |= ERR_ALERT | ERR_FATAL;
6083 goto out;
6084 }
6085
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006086 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006087 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006088 }
William Lallemand0f99e342011-10-12 17:50:54 +02006089
6090 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006091 }
6092 else {
6093 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6094 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006095 err_code |= ERR_ALERT | ERR_FATAL;
6096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006097 }
6098 }
6099 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006100 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006101 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006102 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006103 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006104
Willy Tarreau977b8e42006-12-29 14:19:17 +01006105 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006106 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006107
Willy Tarreaubaaee002006-06-26 02:48:02 +02006108 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006109 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6110 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006111 err_code |= ERR_ALERT | ERR_FATAL;
6112 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006114
6115 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006116 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6117 free(curproxy->conn_src.iface_name);
6118 curproxy->conn_src.iface_name = NULL;
6119 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006120
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006121 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006122 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006123 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006124 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006125 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006126 goto out;
6127 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006128
6129 proto = protocol_by_family(sk->ss_family);
6130 if (!proto || !proto->connect) {
6131 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006132 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006133 err_code |= ERR_ALERT | ERR_FATAL;
6134 goto out;
6135 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006136
6137 if (port1 != port2) {
6138 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6139 file, linenum, args[0], args[1]);
6140 err_code |= ERR_ALERT | ERR_FATAL;
6141 goto out;
6142 }
6143
Willy Tarreauef9a3602012-12-08 22:29:20 +01006144 curproxy->conn_src.source_addr = *sk;
6145 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006146
6147 cur_arg = 2;
6148 while (*(args[cur_arg])) {
6149 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006150#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006151 if (!*args[cur_arg + 1]) {
6152 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6153 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006154 err_code |= ERR_ALERT | ERR_FATAL;
6155 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006156 }
6157
6158 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006159 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6160 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006161 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006162 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6163 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006164 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6165 char *name, *end;
6166
6167 name = args[cur_arg+1] + 7;
6168 while (isspace(*name))
6169 name++;
6170
6171 end = name;
6172 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6173 end++;
6174
Willy Tarreauef9a3602012-12-08 22:29:20 +01006175 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6176 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6177 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6178 curproxy->conn_src.bind_hdr_len = end - name;
6179 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6180 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6181 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006182
6183 /* now look for an occurrence number */
6184 while (isspace(*end))
6185 end++;
6186 if (*end == ',') {
6187 end++;
6188 name = end;
6189 if (*end == '-')
6190 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006191 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006192 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006193 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006194 }
6195
Willy Tarreauef9a3602012-12-08 22:29:20 +01006196 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006197 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6198 " occurrences values smaller than %d.\n",
6199 file, linenum, MAX_HDR_HISTORY);
6200 err_code |= ERR_ALERT | ERR_FATAL;
6201 goto out;
6202 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006203 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006204 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006205
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006206 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006207 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006208 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006209 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006210 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006211 goto out;
6212 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006213
6214 proto = protocol_by_family(sk->ss_family);
6215 if (!proto || !proto->connect) {
6216 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6217 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006218 err_code |= ERR_ALERT | ERR_FATAL;
6219 goto out;
6220 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006221
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006222 if (port1 != port2) {
6223 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6224 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006225 err_code |= ERR_ALERT | ERR_FATAL;
6226 goto out;
6227 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006228 curproxy->conn_src.tproxy_addr = *sk;
6229 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006230 }
6231 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006232#else /* no TPROXY support */
6233 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006234 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006237#endif
6238 cur_arg += 2;
6239 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006240 }
6241
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006242 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6243#ifdef SO_BINDTODEVICE
6244 if (!*args[cur_arg + 1]) {
6245 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6246 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006247 err_code |= ERR_ALERT | ERR_FATAL;
6248 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006249 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006250 free(curproxy->conn_src.iface_name);
6251 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6252 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006253 global.last_checks |= LSTCHK_NETADM;
6254#else
6255 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6256 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006257 err_code |= ERR_ALERT | ERR_FATAL;
6258 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006259#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006260 cur_arg += 2;
6261 continue;
6262 }
6263 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006264 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006268 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006269 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6270 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6271 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006272 err_code |= ERR_ALERT | ERR_FATAL;
6273 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006274 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006275 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006276 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006277 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6278 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006279 err_code |= ERR_ALERT | ERR_FATAL;
6280 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006281 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006282
6283 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006284 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006285 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006286 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006287 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006288 }
6289 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006290 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006291 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006292 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006293 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006294 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006295 }
6296 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006297 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006298 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006299 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006300 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006301 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006302 }
6303 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006304 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006305 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006306 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006307 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006308 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006309 }
6310 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006311 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006312 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006313 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006314 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006315 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006316 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006317 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006318 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006319 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006320 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006321 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006322 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006323 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006324 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006325 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006326 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6327 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006328 err_code |= ERR_ALERT | ERR_FATAL;
6329 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006330 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006331
6332 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006333 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006334 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006335 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006336 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006337 }
6338 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006339 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006340 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006341 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006342 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006343 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006344 }
6345 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006346 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006347 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006348 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006349 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006350 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006351 }
6352 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006353 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006354 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006355 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006356 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006357 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006358 }
6359 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006360 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006361 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006362 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006363 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006364 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006365 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006366 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006367 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006368 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006369 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006370 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006371 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006372 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006373 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006374 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006375
Willy Tarreaubaaee002006-06-26 02:48:02 +02006376 if (curproxy == &defproxy) {
6377 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006378 err_code |= ERR_ALERT | ERR_FATAL;
6379 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006380 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006381 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006382 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006383
Willy Tarreaubaaee002006-06-26 02:48:02 +02006384 if (*(args[1]) == 0) {
6385 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006386 err_code |= ERR_ALERT | ERR_FATAL;
6387 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006388 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006389
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006390 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006391 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6392 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6393 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006394 err_code |= ERR_ALERT | ERR_FATAL;
6395 goto out;
6396 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006397 err_code |= warnif_cond_conflicts(cond,
6398 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6399 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006400 }
6401 else if (*args[2]) {
6402 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6403 file, linenum, args[0], args[2]);
6404 err_code |= ERR_ALERT | ERR_FATAL;
6405 goto out;
6406 }
6407
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006408 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006409 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006410 wl->s = strdup(args[1]);
6411 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006412 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006413 }
6414 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006415 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6417 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006418 err_code |= ERR_ALERT | ERR_FATAL;
6419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006420 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006421
Willy Tarreauade5ec42010-01-28 19:33:49 +01006422 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006423 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006424 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006426 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006427 }
6428 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006429 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006430 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006431 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006433 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006434 }
6435 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006436 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006437 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006438 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006439 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006440 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 }
6442 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006443 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006444 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6445 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006446 err_code |= ERR_ALERT | ERR_FATAL;
6447 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 }
6449
Willy Tarreauade5ec42010-01-28 19:33:49 +01006450 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006451 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006452 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006453 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006454 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006455 }
6456 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006457 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006458 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006459 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006460 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006461 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006462 }
6463 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006464 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006465 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006466 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006467 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006468 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006469 }
6470 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006471 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006472
Willy Tarreaubaaee002006-06-26 02:48:02 +02006473 if (curproxy == &defproxy) {
6474 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006475 err_code |= ERR_ALERT | ERR_FATAL;
6476 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006477 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006478 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006479 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006480
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 if (*(args[1]) == 0) {
6482 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006483 err_code |= ERR_ALERT | ERR_FATAL;
6484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006485 }
6486
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006487 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006488 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6489 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6490 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006491 err_code |= ERR_ALERT | ERR_FATAL;
6492 goto out;
6493 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006494 err_code |= warnif_cond_conflicts(cond,
6495 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6496 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006497 }
6498 else if (*args[2]) {
6499 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6500 file, linenum, args[0], args[2]);
6501 err_code |= ERR_ALERT | ERR_FATAL;
6502 goto out;
6503 }
6504
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006505 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006506 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006507 wl->s = strdup(args[1]);
6508 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 }
6510 else if (!strcmp(args[0], "errorloc") ||
6511 !strcmp(args[0], "errorloc302") ||
6512 !strcmp(args[0], "errorloc303")) { /* error location */
6513 int errnum, errlen;
6514 char *err;
6515
Willy Tarreau977b8e42006-12-29 14:19:17 +01006516 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006517 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006518
Willy Tarreaubaaee002006-06-26 02:48:02 +02006519 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006520 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006521 err_code |= ERR_ALERT | ERR_FATAL;
6522 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006523 }
6524
6525 errnum = atol(args[1]);
6526 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006527 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6528 err = malloc(errlen);
6529 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006530 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006531 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6532 err = malloc(errlen);
6533 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534 }
6535
Willy Tarreau0f772532006-12-23 20:51:41 +01006536 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6537 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006538 chunk_destroy(&curproxy->errmsg[rc]);
6539 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006540 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006541 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006543
6544 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006545 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6546 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006547 free(err);
6548 }
6549 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006550 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6551 int errnum, errlen, fd;
6552 char *err;
6553 struct stat stat;
6554
6555 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006556 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006557
6558 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006559 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006560 err_code |= ERR_ALERT | ERR_FATAL;
6561 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006562 }
6563
6564 fd = open(args[2], O_RDONLY);
6565 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6566 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6567 file, linenum, args[2], args[1]);
6568 if (fd >= 0)
6569 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006570 err_code |= ERR_ALERT | ERR_FATAL;
6571 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006572 }
6573
Willy Tarreau27a674e2009-08-17 07:23:33 +02006574 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006575 errlen = stat.st_size;
6576 } else {
6577 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006578 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006579 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006580 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006581 }
6582
6583 err = malloc(errlen); /* malloc() must succeed during parsing */
6584 errnum = read(fd, err, errlen);
6585 if (errnum != errlen) {
6586 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6587 file, linenum, args[2], args[1]);
6588 close(fd);
6589 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006590 err_code |= ERR_ALERT | ERR_FATAL;
6591 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006592 }
6593 close(fd);
6594
6595 errnum = atol(args[1]);
6596 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6597 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006598 chunk_destroy(&curproxy->errmsg[rc]);
6599 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006600 break;
6601 }
6602 }
6603
6604 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006605 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6606 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006607 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006608 free(err);
6609 }
6610 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006611 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006612 struct cfg_kw_list *kwl;
6613 int index;
6614
6615 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6616 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6617 if (kwl->kw[index].section != CFG_LISTEN)
6618 continue;
6619 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6620 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006621 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006622 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006623 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006624 err_code |= ERR_ALERT | ERR_FATAL;
6625 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006626 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006627 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006628 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006629 err_code |= ERR_WARN;
6630 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006631 }
Willy Tarreau93893792009-07-23 13:19:11 +02006632 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006633 }
6634 }
6635 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006636
Willy Tarreau6daf3432008-01-22 16:44:08 +01006637 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006638 err_code |= ERR_ALERT | ERR_FATAL;
6639 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006640 }
Willy Tarreau93893792009-07-23 13:19:11 +02006641 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006642 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006643 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006644}
6645
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006646int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006647cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6648{
6649#ifdef CONFIG_HAP_NS
6650 const char *err;
6651 const char *item = args[0];
6652
6653 if (!strcmp(item, "namespace_list")) {
6654 return 0;
6655 }
6656 else if (!strcmp(item, "namespace")) {
6657 size_t idx = 1;
6658 const char *current;
6659 while (*(current = args[idx++])) {
6660 err = invalid_char(current);
6661 if (err) {
6662 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6663 file, linenum, *err, item, current);
6664 return ERR_ALERT | ERR_FATAL;
6665 }
6666
6667 if (netns_store_lookup(current, strlen(current))) {
6668 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6669 file, linenum, current);
6670 return ERR_ALERT | ERR_FATAL;
6671 }
6672 if (!netns_store_insert(current)) {
6673 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6674 file, linenum, current);
6675 return ERR_ALERT | ERR_FATAL;
6676 }
6677 }
6678 }
6679
6680 return 0;
6681#else
6682 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6683 file, linenum);
6684 return ERR_ALERT | ERR_FATAL;
6685#endif
6686}
6687
6688int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006689cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6690{
6691
6692 int err_code = 0;
6693 const char *err;
6694
6695 if (!strcmp(args[0], "userlist")) { /* new userlist */
6696 struct userlist *newul;
6697
6698 if (!*args[1]) {
6699 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6700 file, linenum, args[0]);
6701 err_code |= ERR_ALERT | ERR_FATAL;
6702 goto out;
6703 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6705 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006706
6707 err = invalid_char(args[1]);
6708 if (err) {
6709 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6710 file, linenum, *err, args[0], args[1]);
6711 err_code |= ERR_ALERT | ERR_FATAL;
6712 goto out;
6713 }
6714
6715 for (newul = userlist; newul; newul = newul->next)
6716 if (!strcmp(newul->name, args[1])) {
6717 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6718 file, linenum, args[1]);
6719 err_code |= ERR_WARN;
6720 goto out;
6721 }
6722
6723 newul = (struct userlist *)calloc(1, sizeof(struct userlist));
6724 if (!newul) {
6725 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6726 err_code |= ERR_ALERT | ERR_ABORT;
6727 goto out;
6728 }
6729
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006730 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006731 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006732 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6733 err_code |= ERR_ALERT | ERR_ABORT;
6734 goto out;
6735 }
6736
6737 newul->next = userlist;
6738 userlist = newul;
6739
6740 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006741 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006742 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006743 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006744
6745 if (!*args[1]) {
6746 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6747 file, linenum, args[0]);
6748 err_code |= ERR_ALERT | ERR_FATAL;
6749 goto out;
6750 }
6751
6752 err = invalid_char(args[1]);
6753 if (err) {
6754 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6755 file, linenum, *err, args[0], args[1]);
6756 err_code |= ERR_ALERT | ERR_FATAL;
6757 goto out;
6758 }
6759
William Lallemand4ac9f542015-05-28 18:03:51 +02006760 if (!userlist)
6761 goto out;
6762
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006763 for (ag = userlist->groups; ag; ag = ag->next)
6764 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006765 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6766 file, linenum, args[1], userlist->name);
6767 err_code |= ERR_ALERT;
6768 goto out;
6769 }
6770
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006771 ag = calloc(1, sizeof(*ag));
6772 if (!ag) {
6773 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6774 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006775 goto out;
6776 }
6777
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006778 ag->name = strdup(args[1]);
6779 if (!ag) {
6780 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6781 err_code |= ERR_ALERT | ERR_ABORT;
6782 goto out;
6783 }
6784
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006785 cur_arg = 2;
6786
6787 while (*args[cur_arg]) {
6788 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006789 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006790 cur_arg += 2;
6791 continue;
6792 } else {
6793 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6794 file, linenum, args[0]);
6795 err_code |= ERR_ALERT | ERR_FATAL;
6796 goto out;
6797 }
6798 }
6799
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006800 ag->next = userlist->groups;
6801 userlist->groups = ag;
6802
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006803 } else if (!strcmp(args[0], "user")) { /* new user */
6804 struct auth_users *newuser;
6805 int cur_arg;
6806
6807 if (!*args[1]) {
6808 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6809 file, linenum, args[0]);
6810 err_code |= ERR_ALERT | ERR_FATAL;
6811 goto out;
6812 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006813 if (!userlist)
6814 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006815
6816 for (newuser = userlist->users; newuser; newuser = newuser->next)
6817 if (!strcmp(newuser->user, args[1])) {
6818 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6819 file, linenum, args[1], userlist->name);
6820 err_code |= ERR_ALERT;
6821 goto out;
6822 }
6823
6824 newuser = (struct auth_users *)calloc(1, sizeof(struct auth_users));
6825 if (!newuser) {
6826 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6827 err_code |= ERR_ALERT | ERR_ABORT;
6828 goto out;
6829 }
6830
6831 newuser->user = strdup(args[1]);
6832
6833 newuser->next = userlist->users;
6834 userlist->users = newuser;
6835
6836 cur_arg = 2;
6837
6838 while (*args[cur_arg]) {
6839 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006840#ifdef CONFIG_HAP_CRYPT
6841 if (!crypt("", args[cur_arg + 1])) {
6842 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6843 file, linenum, newuser->user);
6844 err_code |= ERR_ALERT | ERR_FATAL;
6845 goto out;
6846 }
6847#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006848 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6849 file, linenum);
6850 err_code |= ERR_ALERT;
6851#endif
6852 newuser->pass = strdup(args[cur_arg + 1]);
6853 cur_arg += 2;
6854 continue;
6855 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6856 newuser->pass = strdup(args[cur_arg + 1]);
6857 newuser->flags |= AU_O_INSECURE;
6858 cur_arg += 2;
6859 continue;
6860 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006861 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006862 cur_arg += 2;
6863 continue;
6864 } else {
6865 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6866 file, linenum, args[0]);
6867 err_code |= ERR_ALERT | ERR_FATAL;
6868 goto out;
6869 }
6870 }
6871 } else {
6872 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6873 err_code |= ERR_ALERT | ERR_FATAL;
6874 }
6875
6876out:
6877 return err_code;
6878}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006879
6880/*
6881 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006882 * Returns the error code, 0 if OK, or any combination of :
6883 * - ERR_ABORT: must abort ASAP
6884 * - ERR_FATAL: we can continue parsing but not start the service
6885 * - ERR_WARN: a warning has been emitted
6886 * - ERR_ALERT: an alert has been emitted
6887 * Only the two first ones can stop processing, the two others are just
6888 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006889 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006890int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006891{
William Lallemand64e84512015-05-12 14:25:37 +02006892 char *thisline;
6893 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006894 FILE *f;
6895 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006896 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006897 struct cfg_section *cs = NULL;
6898 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006899 int readbytes = 0;
6900
6901 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006902 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006903 return -1;
6904 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006905
6906 /* Register internal sections */
6907 if (!cfg_register_section("listen", cfg_parse_listen) ||
6908 !cfg_register_section("frontend", cfg_parse_listen) ||
6909 !cfg_register_section("backend", cfg_parse_listen) ||
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006910 !cfg_register_section("defaults", cfg_parse_listen) ||
6911 !cfg_register_section("global", cfg_parse_global) ||
6912 !cfg_register_section("userlist", cfg_parse_users) ||
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006913 !cfg_register_section("peers", cfg_parse_peers) ||
Simon Horman0d16a402015-01-30 11:22:58 +09006914 !cfg_register_section("mailers", cfg_parse_mailers) ||
Baptiste Assmann325137d2015-04-13 23:40:55 +02006915 !cfg_register_section("namespace_list", cfg_parse_netns) ||
6916 !cfg_register_section("resolvers", cfg_parse_resolvers))
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006917 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006918
Willy Tarreaubaaee002006-06-26 02:48:02 +02006919 if ((f=fopen(file,"r")) == NULL)
6920 return -1;
6921
William Lallemandb2f07452015-05-12 14:27:13 +02006922next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006923 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006924 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006925 char *end;
6926 char *args[MAX_LINE_ARGS + 1];
6927 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006928 int dquote = 0; /* double quote */
6929 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006930
Willy Tarreaubaaee002006-06-26 02:48:02 +02006931 linenum++;
6932
6933 end = line + strlen(line);
6934
William Lallemand64e84512015-05-12 14:25:37 +02006935 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006936 /* Check if we reached the limit and the last char is not \n.
6937 * Watch out for the last line without the terminating '\n'!
6938 */
William Lallemand64e84512015-05-12 14:25:37 +02006939 char *newline;
6940 int newlinesize = linesize * 2;
6941
6942 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
6943 if (newline == NULL) {
6944 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
6945 file, linenum);
6946 err_code |= ERR_ALERT | ERR_FATAL;
6947 continue;
6948 }
6949
6950 readbytes = linesize - 1;
6951 linesize = newlinesize;
6952 thisline = newline;
6953 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006954 }
6955
William Lallemand64e84512015-05-12 14:25:37 +02006956 readbytes = 0;
6957
Willy Tarreaubaaee002006-06-26 02:48:02 +02006958 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02006959 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02006960 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02006961
Willy Tarreaubaaee002006-06-26 02:48:02 +02006962 arg = 0;
6963 args[arg] = line;
6964
6965 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02006966 if (*line == '"' && !squote) { /* double quote outside single quotes */
6967 if (dquote)
6968 dquote = 0;
6969 else
6970 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006971 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006972 end--;
6973 }
6974 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
6975 if (squote)
6976 squote = 0;
6977 else
6978 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02006979 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02006980 end--;
6981 }
6982 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006983 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
6984 * C equivalent value. Other combinations left unchanged (eg: \1).
6985 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02006986 int skip = 0;
6987 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
6988 *line = line[1];
6989 skip = 1;
6990 }
6991 else if (line[1] == 'r') {
6992 *line = '\r';
6993 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02006994 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006995 else if (line[1] == 'n') {
6996 *line = '\n';
6997 skip = 1;
6998 }
6999 else if (line[1] == 't') {
7000 *line = '\t';
7001 skip = 1;
7002 }
7003 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007004 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007005 unsigned char hex1, hex2;
7006 hex1 = toupper(line[2]) - '0';
7007 hex2 = toupper(line[3]) - '0';
7008 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7009 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7010 *line = (hex1<<4) + hex2;
7011 skip = 3;
7012 }
7013 else {
7014 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007015 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007016 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007017 } else if (line[1] == '"') {
7018 *line = '"';
7019 skip = 1;
7020 } else if (line[1] == '\'') {
7021 *line = '\'';
7022 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007023 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7024 *line = '$';
7025 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007026 }
7027 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007028 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007029 end -= skip;
7030 }
7031 line++;
7032 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007033 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007034 /* end of string, end of loop */
7035 *line = 0;
7036 break;
7037 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007038 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007040 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007041 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007042 line++;
7043 args[++arg] = line;
7044 }
William Lallemandb2f07452015-05-12 14:27:13 +02007045 else if (dquote && *line == '$') {
7046 /* environment variables are evaluated inside double quotes */
7047 char *var_beg;
7048 char *var_end;
7049 char save_char;
7050 char *value;
7051 int val_len;
7052 int newlinesize;
7053 int braces = 0;
7054
7055 var_beg = line + 1;
7056 var_end = var_beg;
7057
7058 if (*var_beg == '{') {
7059 var_beg++;
7060 var_end++;
7061 braces = 1;
7062 }
7063
7064 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7065 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7066 err_code |= ERR_ALERT | ERR_FATAL;
7067 goto next_line; /* skip current line */
7068 }
7069
7070 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7071 var_end++;
7072
7073 save_char = *var_end;
7074 *var_end = '\0';
7075 value = getenv(var_beg);
7076 *var_end = save_char;
7077 val_len = value ? strlen(value) : 0;
7078
7079 if (braces) {
7080 if (*var_end == '}') {
7081 var_end++;
7082 braces = 0;
7083 } else {
7084 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7085 err_code |= ERR_ALERT | ERR_FATAL;
7086 goto next_line; /* skip current line */
7087 }
7088 }
7089
7090 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7091
7092 /* if not enough space in thisline */
7093 if (newlinesize > linesize) {
7094 char *newline;
7095
7096 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7097 if (newline == NULL) {
7098 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7099 err_code |= ERR_ALERT | ERR_FATAL;
7100 goto next_line; /* slip current line */
7101 }
7102 /* recompute pointers if realloc returns a new pointer */
7103 if (newline != thisline) {
7104 int i;
7105 int diff;
7106
7107 for (i = 0; i <= arg; i++) {
7108 diff = args[i] - thisline;
7109 args[i] = newline + diff;
7110 }
7111
7112 diff = var_end - thisline;
7113 var_end = newline + diff;
7114 diff = end - thisline;
7115 end = newline + diff;
7116 diff = line - thisline;
7117 line = newline + diff;
7118 thisline = newline;
7119 }
7120 linesize = newlinesize;
7121 }
7122
7123 /* insert value inside the line */
7124 memmove(line + val_len, var_end, end - var_end + 1);
7125 memcpy(line, value, val_len);
7126 end += val_len - (var_end - line);
7127 line += val_len;
7128 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007129 else {
7130 line++;
7131 }
7132 }
William Lallemandb2f07452015-05-12 14:27:13 +02007133
William Lallemandf9873ba2015-05-05 17:37:14 +02007134 if (dquote) {
7135 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7136 err_code |= ERR_ALERT | ERR_FATAL;
7137 }
7138
7139 if (squote) {
7140 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7141 err_code |= ERR_ALERT | ERR_FATAL;
7142 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007143
7144 /* empty line */
7145 if (!**args)
7146 continue;
7147
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007148 if (*line) {
7149 /* we had to stop due to too many args.
7150 * Let's terminate the string, print the offending part then cut the
7151 * last arg.
7152 */
7153 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7154 line++;
7155 *line = '\0';
7156
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007157 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007158 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007159 err_code |= ERR_ALERT | ERR_FATAL;
7160 args[arg] = line;
7161 }
7162
Willy Tarreau540abe42007-05-02 20:50:16 +02007163 /* zero out remaining args and ensure that at least one entry
7164 * is zeroed out.
7165 */
7166 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007167 args[arg] = line;
7168 }
7169
Willy Tarreau3842f002009-06-14 11:39:52 +02007170 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007171 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007172 char *tmp;
7173
Willy Tarreau3842f002009-06-14 11:39:52 +02007174 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007175 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007176 for (arg=0; *args[arg+1]; arg++)
7177 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007178 *tmp = '\0'; // fix the next arg to \0
7179 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007180 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007181 else if (!strcmp(args[0], "default")) {
7182 kwm = KWM_DEF;
7183 for (arg=0; *args[arg+1]; arg++)
7184 args[arg] = args[arg+1]; // shift args after inversion
7185 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007186
William Lallemand0f99e342011-10-12 17:50:54 +02007187 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7188 strcmp(args[0], "log") != 0) {
7189 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007190 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007191 }
7192
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007193 /* detect section start */
7194 list_for_each_entry(ics, &sections, list) {
7195 if (strcmp(args[0], ics->section_name) == 0) {
7196 cursection = ics->section_name;
7197 cs = ics;
7198 break;
7199 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007200 }
7201
Willy Tarreaubaaee002006-06-26 02:48:02 +02007202 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007203 if (cs)
7204 err_code |= cs->section_parser(file, linenum, args, kwm);
7205 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007206 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007207 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007208 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007209
7210 if (err_code & ERR_ABORT)
7211 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007212 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007213 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007214 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007215 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007216 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007217}
7218
Willy Tarreau64ab6072014-09-16 12:17:36 +02007219/* This function propagates processes from frontend <from> to backend <to> so
7220 * that it is always guaranteed that a backend pointed to by a frontend is
7221 * bound to all of its processes. After that, if the target is a "listen"
7222 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007223 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007224 * checked first to ensure that <to> is already bound to all processes of
7225 * <from>, there is no risk of looping and we ensure to follow the shortest
7226 * path to the destination.
7227 *
7228 * It is possible to set <to> to NULL for the first call so that the function
7229 * takes care of visiting the initial frontend in <from>.
7230 *
7231 * It is important to note that the function relies on the fact that all names
7232 * have already been resolved.
7233 */
7234void propagate_processes(struct proxy *from, struct proxy *to)
7235{
7236 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007237
7238 if (to) {
7239 /* check whether we need to go down */
7240 if (from->bind_proc &&
7241 (from->bind_proc & to->bind_proc) == from->bind_proc)
7242 return;
7243
7244 if (!from->bind_proc && !to->bind_proc)
7245 return;
7246
7247 to->bind_proc = from->bind_proc ?
7248 (to->bind_proc | from->bind_proc) : 0;
7249
7250 /* now propagate down */
7251 from = to;
7252 }
7253
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007254 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007255 return;
7256
Willy Tarreauf6b70012014-12-18 14:00:43 +01007257 if (from->state == PR_STSTOPPED)
7258 return;
7259
Willy Tarreau64ab6072014-09-16 12:17:36 +02007260 /* default_backend */
7261 if (from->defbe.be)
7262 propagate_processes(from, from->defbe.be);
7263
7264 /* use_backend */
7265 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007266 if (rule->dynamic)
7267 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007268 to = rule->be.backend;
7269 propagate_processes(from, to);
7270 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007271}
7272
Willy Tarreaubb925012009-07-23 13:36:36 +02007273/*
7274 * Returns the error code, 0 if OK, or any combination of :
7275 * - ERR_ABORT: must abort ASAP
7276 * - ERR_FATAL: we can continue parsing but not start the service
7277 * - ERR_WARN: a warning has been emitted
7278 * - ERR_ALERT: an alert has been emitted
7279 * Only the two first ones can stop processing, the two others are just
7280 * indicators.
7281 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007282int check_config_validity()
7283{
7284 int cfgerr = 0;
7285 struct proxy *curproxy = NULL;
7286 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007287 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007288 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007289 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007290
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007291 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007292 /*
7293 * Now, check for the integrity of all that we have collected.
7294 */
7295
7296 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007297 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007298
Willy Tarreau193b8c62012-11-22 00:17:38 +01007299 if (!global.tune.max_http_hdr)
7300 global.tune.max_http_hdr = MAX_HTTP_HDR;
7301
7302 if (!global.tune.cookie_len)
7303 global.tune.cookie_len = CAPTURE_LEN;
7304
7305 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7306
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007307 /* Post initialisation of the users and groups lists. */
7308 err_code = userlist_postinit();
7309 if (err_code != ERR_NONE)
7310 goto out;
7311
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007312 /* first, we will invert the proxy list order */
7313 curproxy = NULL;
7314 while (proxy) {
7315 struct proxy *next;
7316
7317 next = proxy->next;
7318 proxy->next = curproxy;
7319 curproxy = proxy;
7320 if (!next)
7321 break;
7322 proxy = next;
7323 }
7324
Willy Tarreau419ead82014-09-16 13:41:21 +02007325 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007326 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007327 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007328 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007329 struct act_rule *trule;
7330 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007331 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007332 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007333 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007334
Willy Tarreau050536d2012-10-04 08:47:34 +02007335 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007336 /* proxy ID not set, use automatic numbering with first
7337 * spare entry starting with next_pxid.
7338 */
7339 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7340 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7341 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007342 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007343 next_pxid++;
7344
Willy Tarreau55ea7572007-06-17 19:56:27 +02007345
Willy Tarreaubaaee002006-06-26 02:48:02 +02007346 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007347 /* ensure we don't keep listeners uselessly bound */
7348 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007349 free((void *)curproxy->table.peers.name);
7350 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007351 continue;
7352 }
7353
Willy Tarreau102df612014-05-07 23:56:38 +02007354 /* Check multi-process mode compatibility for the current proxy */
7355
7356 if (curproxy->bind_proc) {
7357 /* an explicit bind-process was specified, let's check how many
7358 * processes remain.
7359 */
David Carliere6c39412015-07-02 07:00:17 +00007360 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007361
7362 curproxy->bind_proc &= nbits(global.nbproc);
7363 if (!curproxy->bind_proc && nbproc == 1) {
7364 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);
7365 curproxy->bind_proc = 1;
7366 }
7367 else if (!curproxy->bind_proc && nbproc > 1) {
7368 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);
7369 curproxy->bind_proc = 0;
7370 }
7371 }
7372
Willy Tarreau3d209582014-05-09 17:06:11 +02007373 /* check and reduce the bind-proc of each listener */
7374 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7375 unsigned long mask;
7376
7377 if (!bind_conf->bind_proc)
7378 continue;
7379
7380 mask = nbits(global.nbproc);
7381 if (curproxy->bind_proc)
7382 mask &= curproxy->bind_proc;
7383 /* mask cannot be null here thanks to the previous checks */
7384
David Carliere6c39412015-07-02 07:00:17 +00007385 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007386 bind_conf->bind_proc &= mask;
7387
7388 if (!bind_conf->bind_proc && nbproc == 1) {
7389 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",
7390 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7391 bind_conf->bind_proc = mask & ~(mask - 1);
7392 }
7393 else if (!bind_conf->bind_proc && nbproc > 1) {
7394 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",
7395 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7396 bind_conf->bind_proc = 0;
7397 }
7398 }
7399
Willy Tarreauff01a212009-03-15 13:46:16 +01007400 switch (curproxy->mode) {
7401 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007402 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007403 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007404 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7405 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007406 cfgerr++;
7407 }
7408
7409 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007410 Warning("config : servers will be ignored for %s '%s'.\n",
7411 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007412 break;
7413
7414 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007415 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007416 break;
7417
7418 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007419 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007420 break;
7421 }
7422
Willy Tarreauf3934b82015-08-11 11:36:45 +02007423 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7424 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7425 proxy_type_str(curproxy), curproxy->id);
7426 err_code |= ERR_WARN;
7427 }
7428
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007429 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007430 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007431 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007432 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7433 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007434 cfgerr++;
7435 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007436#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007437 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007438 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7439 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007440 cfgerr++;
7441 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007442#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007443 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007444 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7445 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007446 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007447 }
7448 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007449 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007450 /* If no LB algo is set in a backend, and we're not in
7451 * transparent mode, dispatch mode nor proxy mode, we
7452 * want to use balance roundrobin by default.
7453 */
7454 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7455 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007456 }
7457 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007458
Willy Tarreau1620ec32011-08-06 17:05:02 +02007459 if (curproxy->options & PR_O_DISPATCH)
7460 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7461 else if (curproxy->options & PR_O_HTTP_PROXY)
7462 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7463 else if (curproxy->options & PR_O_TRANSP)
7464 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007465
Willy Tarreau1620ec32011-08-06 17:05:02 +02007466 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7467 if (curproxy->options & PR_O_DISABLE404) {
7468 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7469 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7470 err_code |= ERR_WARN;
7471 curproxy->options &= ~PR_O_DISABLE404;
7472 }
7473 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7474 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7475 "send-state", proxy_type_str(curproxy), curproxy->id);
7476 err_code |= ERR_WARN;
7477 curproxy->options &= ~PR_O2_CHK_SNDST;
7478 }
Willy Tarreauef781042010-01-27 11:53:01 +01007479 }
7480
Simon Horman98637e52014-06-20 12:30:16 +09007481 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7482 if (!global.external_check) {
7483 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7484 curproxy->id, "option external-check");
7485 cfgerr++;
7486 }
7487 if (!curproxy->check_command) {
7488 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7489 curproxy->id, "option external-check");
7490 cfgerr++;
7491 }
7492 }
7493
Simon Horman64e34162015-02-06 11:11:57 +09007494 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007495 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7496 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007497 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7498 "'email-alert myhostname', or 'email-alert to' "
7499 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007500 "to be present).\n",
7501 proxy_type_str(curproxy), curproxy->id);
7502 err_code |= ERR_WARN;
7503 free_email_alert(curproxy);
7504 }
7505 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007506 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007507 }
7508
Simon Horman98637e52014-06-20 12:30:16 +09007509 if (curproxy->check_command) {
7510 int clear = 0;
7511 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7512 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7513 "external-check command", proxy_type_str(curproxy), curproxy->id);
7514 err_code |= ERR_WARN;
7515 clear = 1;
7516 }
7517 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007518 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007519 curproxy->id, "external-check command");
7520 cfgerr++;
7521 }
7522 if (clear) {
7523 free(curproxy->check_command);
7524 curproxy->check_command = NULL;
7525 }
7526 }
7527
7528 if (curproxy->check_path) {
7529 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7530 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7531 "external-check path", proxy_type_str(curproxy), curproxy->id);
7532 err_code |= ERR_WARN;
7533 free(curproxy->check_path);
7534 curproxy->check_path = NULL;
7535 }
7536 }
7537
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007538 /* if a default backend was specified, let's find it */
7539 if (curproxy->defbe.name) {
7540 struct proxy *target;
7541
Willy Tarreauafb39922015-05-26 12:04:09 +02007542 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007543 if (!target) {
7544 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7545 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007546 cfgerr++;
7547 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007548 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7549 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007550 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007551 } else if (target->mode != curproxy->mode &&
7552 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7553
7554 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7555 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7556 curproxy->conf.file, curproxy->conf.line,
7557 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7558 target->conf.file, target->conf.line);
7559 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007560 } else {
7561 free(curproxy->defbe.name);
7562 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007563
7564 /* Emit a warning if this proxy also has some servers */
7565 if (curproxy->srv) {
7566 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7567 curproxy->id);
7568 err_code |= ERR_WARN;
7569 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007570 }
7571 }
7572
Willy Tarreau55ea7572007-06-17 19:56:27 +02007573 /* find the target proxy for 'use_backend' rules */
7574 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007575 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007576 struct logformat_node *node;
7577 char *pxname;
7578
7579 /* Try to parse the string as a log format expression. If the result
7580 * of the parsing is only one entry containing a simple string, then
7581 * it's a standard string corresponding to a static rule, thus the
7582 * parsing is cancelled and be.name is restored to be resolved.
7583 */
7584 pxname = rule->be.name;
7585 LIST_INIT(&rule->be.expr);
7586 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7587 curproxy->conf.args.file, curproxy->conf.args.line);
7588 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7589
7590 if (!LIST_ISEMPTY(&rule->be.expr)) {
7591 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7592 rule->dynamic = 1;
7593 free(pxname);
7594 continue;
7595 }
7596 /* simple string: free the expression and fall back to static rule */
7597 free(node->arg);
7598 free(node);
7599 }
7600
7601 rule->dynamic = 0;
7602 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007603
Willy Tarreauafb39922015-05-26 12:04:09 +02007604 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007605 if (!target) {
7606 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7607 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007608 cfgerr++;
7609 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007610 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7611 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007612 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007613 } else if (target->mode != curproxy->mode &&
7614 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7615
7616 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7617 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7618 curproxy->conf.file, curproxy->conf.line,
7619 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7620 target->conf.file, target->conf.line);
7621 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007622 } else {
7623 free((void *)rule->be.name);
7624 rule->be.backend = target;
7625 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007626 }
7627
Willy Tarreau64ab6072014-09-16 12:17:36 +02007628 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007629 list_for_each_entry(srule, &curproxy->server_rules, list) {
7630 struct server *target = findserver(curproxy, srule->srv.name);
7631
7632 if (!target) {
7633 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7634 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7635 cfgerr++;
7636 continue;
7637 }
7638 free((void *)srule->srv.name);
7639 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007640 }
7641
Emeric Brunb982a3d2010-01-04 15:45:53 +01007642 /* find the target table for 'stick' rules */
7643 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7644 struct proxy *target;
7645
Emeric Brun1d33b292010-01-04 15:47:17 +01007646 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7647 if (mrule->flags & STK_IS_STORE)
7648 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7649
Emeric Brunb982a3d2010-01-04 15:45:53 +01007650 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007651 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007652 else
7653 target = curproxy;
7654
7655 if (!target) {
7656 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7657 curproxy->id, mrule->table.name);
7658 cfgerr++;
7659 }
7660 else if (target->table.size == 0) {
7661 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7662 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7663 cfgerr++;
7664 }
Willy Tarreau12785782012-04-27 21:37:17 +02007665 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7666 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007667 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7668 cfgerr++;
7669 }
7670 else {
7671 free((void *)mrule->table.name);
7672 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007673 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007674 }
7675 }
7676
7677 /* find the target table for 'store response' rules */
7678 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7679 struct proxy *target;
7680
Emeric Brun1d33b292010-01-04 15:47:17 +01007681 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7682
Emeric Brunb982a3d2010-01-04 15:45:53 +01007683 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007684 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007685 else
7686 target = curproxy;
7687
7688 if (!target) {
7689 Alert("Proxy '%s': unable to find store table '%s'.\n",
7690 curproxy->id, mrule->table.name);
7691 cfgerr++;
7692 }
7693 else if (target->table.size == 0) {
7694 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7695 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7696 cfgerr++;
7697 }
Willy Tarreau12785782012-04-27 21:37:17 +02007698 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7699 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007700 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7701 cfgerr++;
7702 }
7703 else {
7704 free((void *)mrule->table.name);
7705 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007706 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007707 }
7708 }
7709
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007710 /* find the target table for 'tcp-request' layer 4 rules */
7711 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7712 struct proxy *target;
7713
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007714 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007715 continue;
7716
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007717 if (trule->arg.trk_ctr.table.n)
7718 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007719 else
7720 target = curproxy;
7721
7722 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007723 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007724 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007725 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007726 cfgerr++;
7727 }
7728 else if (target->table.size == 0) {
7729 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007730 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007731 cfgerr++;
7732 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007733 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007734 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007735 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007736 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007737 cfgerr++;
7738 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007739 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007740 free(trule->arg.trk_ctr.table.n);
7741 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007742 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007743 * to pass a list of counters to track and allocate them right here using
7744 * stktable_alloc_data_type().
7745 */
7746 }
7747 }
7748
Willy Tarreaud1f96522010-08-03 19:34:32 +02007749 /* find the target table for 'tcp-request' layer 6 rules */
7750 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7751 struct proxy *target;
7752
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007753 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007754 continue;
7755
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007756 if (trule->arg.trk_ctr.table.n)
7757 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007758 else
7759 target = curproxy;
7760
7761 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007762 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007763 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007764 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007765 cfgerr++;
7766 }
7767 else if (target->table.size == 0) {
7768 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007769 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007770 cfgerr++;
7771 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007772 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007773 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007774 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007775 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007776 cfgerr++;
7777 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007778 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007779 free(trule->arg.trk_ctr.table.n);
7780 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007781 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007782 * to pass a list of counters to track and allocate them right here using
7783 * stktable_alloc_data_type().
7784 */
7785 }
7786 }
7787
Baptiste Assmanne9544932015-11-03 23:31:35 +01007788 /* parse http-request capture rules to ensure id really exists */
7789 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7790 if (hrqrule->action != ACT_CUSTOM ||
7791 hrqrule->action_ptr != http_action_req_capture_by_id)
7792 continue;
7793
7794 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7795 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7796 curproxy->id, hrqrule->arg.capid.idx);
7797 cfgerr++;
7798 }
7799 }
7800
7801 /* parse http-response capture rules to ensure id really exists */
7802 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7803 if (hrqrule->action != ACT_CUSTOM ||
7804 hrqrule->action_ptr != http_action_res_capture_by_id)
7805 continue;
7806
7807 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7808 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7809 curproxy->id, hrqrule->arg.capid.idx);
7810 cfgerr++;
7811 }
7812 }
7813
Willy Tarreau09448f72014-06-25 18:12:15 +02007814 /* find the target table for 'http-request' layer 7 rules */
7815 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7816 struct proxy *target;
7817
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007818 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007819 continue;
7820
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007821 if (hrqrule->arg.trk_ctr.table.n)
7822 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007823 else
7824 target = curproxy;
7825
7826 if (!target) {
7827 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007828 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Willy Tarreau09448f72014-06-25 18:12:15 +02007829 http_req_trk_idx(hrqrule->action));
7830 cfgerr++;
7831 }
7832 else if (target->table.size == 0) {
7833 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007834 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007835 cfgerr++;
7836 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007837 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007838 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007839 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau09448f72014-06-25 18:12:15 +02007840 http_req_trk_idx(hrqrule->action));
7841 cfgerr++;
7842 }
7843 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007844 free(hrqrule->arg.trk_ctr.table.n);
7845 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007846 /* Note: if we decide to enhance the track-sc syntax, we may be able
7847 * to pass a list of counters to track and allocate them right here using
7848 * stktable_alloc_data_type().
7849 */
7850 }
7851 }
7852
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007853 /* move any "block" rules at the beginning of the http-request rules */
7854 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7855 /* insert block_rules into http_req_rules at the beginning */
7856 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7857 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7858 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7859 curproxy->http_req_rules.n = curproxy->block_rules.n;
7860 LIST_INIT(&curproxy->block_rules);
7861 }
7862
Emeric Brun32da3c42010-09-23 18:39:19 +02007863 if (curproxy->table.peers.name) {
7864 struct peers *curpeers = peers;
7865
7866 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7867 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7868 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007869 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007870 break;
7871 }
7872 }
7873
7874 if (!curpeers) {
7875 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7876 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007877 free((void *)curproxy->table.peers.name);
7878 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007879 cfgerr++;
7880 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007881 else if (curpeers->state == PR_STSTOPPED) {
7882 /* silently disable this peers section */
7883 curproxy->table.peers.p = NULL;
7884 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007885 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007886 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7887 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007888 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007889 cfgerr++;
7890 }
7891 }
7892
Simon Horman9dc49962015-01-30 11:22:59 +09007893
7894 if (curproxy->email_alert.mailers.name) {
7895 struct mailers *curmailers = mailers;
7896
7897 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7898 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7899 free(curproxy->email_alert.mailers.name);
7900 curproxy->email_alert.mailers.m = curmailers;
7901 curmailers->users++;
7902 break;
7903 }
7904 }
7905
7906 if (!curmailers) {
7907 Alert("Proxy '%s': unable to find mailers '%s'.\n",
7908 curproxy->id, curproxy->email_alert.mailers.name);
7909 free_email_alert(curproxy);
7910 cfgerr++;
7911 }
7912 }
7913
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007914 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01007915 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007916 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
7917 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
7918 "proxy", curproxy->id);
7919 cfgerr++;
7920 goto out_uri_auth_compat;
7921 }
7922
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007923 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007924 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007925 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01007926 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007927
Willy Tarreau95fa4692010-02-01 13:05:50 +01007928 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
7929 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007930
7931 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007932 uri_auth_compat_req[i++] = "realm";
7933 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
7934 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007935
Willy Tarreau95fa4692010-02-01 13:05:50 +01007936 uri_auth_compat_req[i++] = "unless";
7937 uri_auth_compat_req[i++] = "{";
7938 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
7939 uri_auth_compat_req[i++] = "}";
7940 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007941
Willy Tarreauff011f22011-01-06 17:51:27 +01007942 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
7943 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01007944 cfgerr++;
7945 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007946 }
7947
Willy Tarreauff011f22011-01-06 17:51:27 +01007948 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01007949
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007950 if (curproxy->uri_auth->auth_realm) {
7951 free(curproxy->uri_auth->auth_realm);
7952 curproxy->uri_auth->auth_realm = NULL;
7953 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01007954
7955 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01007956 }
7957out_uri_auth_compat:
7958
Dragan Dosen43885c72015-10-01 13:18:13 +02007959 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02007960 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02007961 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
7962 if (!curproxy->conf.logformat_sd_string) {
7963 /* set the default logformat_sd_string */
7964 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
7965 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007966 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02007967 }
Dragan Dosen1322d092015-09-22 16:05:32 +02007968 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02007969
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007970 /* compile the log format */
7971 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02007972 if (curproxy->conf.logformat_string != default_http_log_format &&
7973 curproxy->conf.logformat_string != default_tcp_log_format &&
7974 curproxy->conf.logformat_string != clf_http_log_format)
7975 free(curproxy->conf.logformat_string);
7976 curproxy->conf.logformat_string = NULL;
7977 free(curproxy->conf.lfs_file);
7978 curproxy->conf.lfs_file = NULL;
7979 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007980
7981 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
7982 free(curproxy->conf.logformat_sd_string);
7983 curproxy->conf.logformat_sd_string = NULL;
7984 free(curproxy->conf.lfsd_file);
7985 curproxy->conf.lfsd_file = NULL;
7986 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007987 }
7988
Willy Tarreau62a61232013-04-12 18:13:46 +02007989 if (curproxy->conf.logformat_string) {
7990 curproxy->conf.args.ctx = ARGC_LOG;
7991 curproxy->conf.args.file = curproxy->conf.lfs_file;
7992 curproxy->conf.args.line = curproxy->conf.lfs_line;
7993 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01007994 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02007995 curproxy->conf.args.file = NULL;
7996 curproxy->conf.args.line = 0;
7997 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02007998
Dragan Dosen0b85ece2015-09-25 19:17:44 +02007999 if (curproxy->conf.logformat_sd_string) {
8000 curproxy->conf.args.ctx = ARGC_LOGSD;
8001 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8002 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8003 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8004 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8005 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8006 curproxy->conf.args.file = NULL;
8007 curproxy->conf.args.line = 0;
8008 }
8009
Willy Tarreau62a61232013-04-12 18:13:46 +02008010 if (curproxy->conf.uniqueid_format_string) {
8011 curproxy->conf.args.ctx = ARGC_UIF;
8012 curproxy->conf.args.file = curproxy->conf.uif_file;
8013 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008014 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008015 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008016 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008017 curproxy->conf.args.file = NULL;
8018 curproxy->conf.args.line = 0;
8019 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008020
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008021 /* only now we can check if some args remain unresolved.
8022 * This must be done after the users and groups resolution.
8023 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008024 cfgerr += smp_resolve_args(curproxy);
8025 if (!cfgerr)
8026 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008027
Willy Tarreau2738a142006-07-08 17:28:09 +02008028 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008029 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008030 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008031 (!curproxy->timeout.connect ||
8032 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008033 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008034 " | While not properly invalid, you will certainly encounter various problems\n"
8035 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008036 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008037 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008038 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008039 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008040
Willy Tarreau1fa31262007-12-03 00:36:16 +01008041 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8042 * We must still support older configurations, so let's find out whether those
8043 * parameters have been set or must be copied from contimeouts.
8044 */
8045 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008046 if (!curproxy->timeout.tarpit ||
8047 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008048 /* tarpit timeout not set. We search in the following order:
8049 * default.tarpit, curr.connect, default.connect.
8050 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008051 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008052 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008053 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008054 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008055 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008056 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008057 }
8058 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008059 (!curproxy->timeout.queue ||
8060 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008061 /* queue timeout not set. We search in the following order:
8062 * default.queue, curr.connect, default.connect.
8063 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008064 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008065 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008066 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008067 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008068 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008069 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008070 }
8071 }
8072
Willy Tarreau1620ec32011-08-06 17:05:02 +02008073 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008074 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
8075 curproxy->check_req = (char *)malloc(curproxy->check_len);
8076 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008077 }
8078
Willy Tarreau215663d2014-06-13 18:30:23 +02008079 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8080 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8081 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8082 proxy_type_str(curproxy), curproxy->id);
8083 err_code |= ERR_WARN;
8084 }
8085
Willy Tarreau193b8c62012-11-22 00:17:38 +01008086 /* ensure that cookie capture length is not too large */
8087 if (curproxy->capture_len >= global.tune.cookie_len) {
8088 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8089 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8090 err_code |= ERR_WARN;
8091 curproxy->capture_len = global.tune.cookie_len - 1;
8092 }
8093
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008094 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008095 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008096 curproxy->req_cap_pool = create_pool("ptrcap",
8097 curproxy->nb_req_cap * sizeof(char *),
8098 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008099 }
8100
8101 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008102 curproxy->rsp_cap_pool = create_pool("ptrcap",
8103 curproxy->nb_rsp_cap * sizeof(char *),
8104 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008105 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008106
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008107 switch (curproxy->load_server_state_from_file) {
8108 case PR_SRV_STATE_FILE_UNSPEC:
8109 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8110 break;
8111 case PR_SRV_STATE_FILE_GLOBAL:
8112 if (!global.server_state_file) {
8113 Warning("config : backend '%s' configured to load server state file from global section 'server-state-file' directive. Unfortunately, 'server-state-file' is not set!\n",
8114 curproxy->id);
8115 err_code |= ERR_WARN;
8116 }
8117 break;
8118 }
8119
Willy Tarreaubaaee002006-06-26 02:48:02 +02008120 /* first, we will invert the servers list order */
8121 newsrv = NULL;
8122 while (curproxy->srv) {
8123 struct server *next;
8124
8125 next = curproxy->srv->next;
8126 curproxy->srv->next = newsrv;
8127 newsrv = curproxy->srv;
8128 if (!next)
8129 break;
8130 curproxy->srv = next;
8131 }
8132
Willy Tarreau17edc812014-01-03 12:14:34 +01008133 /* Check that no server name conflicts. This causes trouble in the stats.
8134 * We only emit a warning for the first conflict affecting each server,
8135 * in order to avoid combinatory explosion if all servers have the same
8136 * name. We do that only for servers which do not have an explicit ID,
8137 * because these IDs were made also for distinguishing them and we don't
8138 * want to annoy people who correctly manage them.
8139 */
8140 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8141 struct server *other_srv;
8142
8143 if (newsrv->puid)
8144 continue;
8145
8146 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8147 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8148 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8149 newsrv->conf.file, newsrv->conf.line,
8150 proxy_type_str(curproxy), curproxy->id,
8151 newsrv->id, other_srv->conf.line);
8152 break;
8153 }
8154 }
8155 }
8156
Willy Tarreaudd701652010-05-25 23:03:02 +02008157 /* assign automatic UIDs to servers which don't have one yet */
8158 next_id = 1;
8159 newsrv = curproxy->srv;
8160 while (newsrv != NULL) {
8161 if (!newsrv->puid) {
8162 /* server ID not set, use automatic numbering with first
8163 * spare entry starting with next_svid.
8164 */
8165 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8166 newsrv->conf.id.key = newsrv->puid = next_id;
8167 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8168 }
8169 next_id++;
8170 newsrv = newsrv->next;
8171 }
8172
Willy Tarreau20697042007-11-15 23:26:18 +01008173 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008174 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008175
Willy Tarreau62c3be22012-01-20 13:12:32 +01008176 /*
8177 * If this server supports a maxconn parameter, it needs a dedicated
8178 * tasks to fill the emptied slots when a connection leaves.
8179 * Also, resolve deferred tracking dependency if needed.
8180 */
8181 newsrv = curproxy->srv;
8182 while (newsrv != NULL) {
8183 if (newsrv->minconn > newsrv->maxconn) {
8184 /* Only 'minconn' was specified, or it was higher than or equal
8185 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8186 * this will avoid further useless expensive computations.
8187 */
8188 newsrv->maxconn = newsrv->minconn;
8189 } else if (newsrv->maxconn && !newsrv->minconn) {
8190 /* minconn was not specified, so we set it to maxconn */
8191 newsrv->minconn = newsrv->maxconn;
8192 }
8193
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008194#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008195 if (newsrv->use_ssl || newsrv->check.use_ssl)
8196 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008197#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008198
Willy Tarreau2f075e92013-12-03 11:11:34 +01008199 /* set the check type on the server */
8200 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8201
Willy Tarreau62c3be22012-01-20 13:12:32 +01008202 if (newsrv->trackit) {
8203 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008204 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008205 char *pname, *sname;
8206
8207 pname = newsrv->trackit;
8208 sname = strrchr(pname, '/');
8209
8210 if (sname)
8211 *sname++ = '\0';
8212 else {
8213 sname = pname;
8214 pname = NULL;
8215 }
8216
8217 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008218 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008219 if (!px) {
8220 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8221 proxy_type_str(curproxy), curproxy->id,
8222 newsrv->id, pname);
8223 cfgerr++;
8224 goto next_srv;
8225 }
8226 } else
8227 px = curproxy;
8228
8229 srv = findserver(px, sname);
8230 if (!srv) {
8231 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8232 proxy_type_str(curproxy), curproxy->id,
8233 newsrv->id, sname);
8234 cfgerr++;
8235 goto next_srv;
8236 }
8237
Willy Tarreau32091232014-05-16 13:52:00 +02008238 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8239 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8240 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008241 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008242 "tracking as it does not have any check nor agent enabled.\n",
8243 proxy_type_str(curproxy), curproxy->id,
8244 newsrv->id, px->id, srv->id);
8245 cfgerr++;
8246 goto next_srv;
8247 }
8248
8249 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8250
8251 if (loop) {
8252 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8253 "belongs to a tracking chain looping back to %s/%s.\n",
8254 proxy_type_str(curproxy), curproxy->id,
8255 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008256 cfgerr++;
8257 goto next_srv;
8258 }
8259
8260 if (curproxy != px &&
8261 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8262 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8263 "tracking: disable-on-404 option inconsistency.\n",
8264 proxy_type_str(curproxy), curproxy->id,
8265 newsrv->id, px->id, srv->id);
8266 cfgerr++;
8267 goto next_srv;
8268 }
8269
8270 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008271 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008272 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008273 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008274 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008275 }
8276
8277 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008278 newsrv->tracknext = srv->trackers;
8279 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008280
8281 free(newsrv->trackit);
8282 newsrv->trackit = NULL;
8283 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008284
8285 /*
8286 * resolve server's resolvers name and update the resolvers pointer
8287 * accordingly
8288 */
8289 if (newsrv->resolvers_id) {
8290 struct dns_resolvers *curr_resolvers;
8291 int found;
8292
8293 found = 0;
8294 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8295 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8296 found = 1;
8297 break;
8298 }
8299 }
8300
8301 if (!found) {
8302 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8303 proxy_type_str(curproxy), curproxy->id,
8304 newsrv->id, newsrv->resolvers_id);
8305 cfgerr++;
8306 } else {
8307 free(newsrv->resolvers_id);
8308 newsrv->resolvers_id = NULL;
8309 if (newsrv->resolution)
8310 newsrv->resolution->resolvers = curr_resolvers;
8311 }
8312 }
8313 else {
8314 /* if no resolvers section associated to this server
8315 * we can clean up the associated resolution structure
8316 */
8317 if (newsrv->resolution) {
8318 free(newsrv->resolution->hostname_dn);
8319 newsrv->resolution->hostname_dn = NULL;
8320 free(newsrv->resolution);
8321 newsrv->resolution = NULL;
8322 }
8323 }
8324
Willy Tarreau62c3be22012-01-20 13:12:32 +01008325 next_srv:
8326 newsrv = newsrv->next;
8327 }
8328
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008329 /* We have to initialize the server lookup mechanism depending
8330 * on what LB algorithm was choosen.
8331 */
8332
8333 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8334 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8335 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008336 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8337 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8338 init_server_map(curproxy);
8339 } else {
8340 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8341 fwrr_init_server_groups(curproxy);
8342 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008343 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008344
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008345 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008346 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8347 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8348 fwlc_init_server_tree(curproxy);
8349 } else {
8350 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8351 fas_init_server_tree(curproxy);
8352 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008353 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008354
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008355 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008356 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8357 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8358 chash_init_server_tree(curproxy);
8359 } else {
8360 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8361 init_server_map(curproxy);
8362 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008363 break;
8364 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008365
8366 if (curproxy->options & PR_O_LOGASAP)
8367 curproxy->to_log &= ~LW_BYTES;
8368
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008369 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008370 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8371 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008372 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8373 proxy_type_str(curproxy), curproxy->id);
8374 err_code |= ERR_WARN;
8375 }
8376
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008377 if (curproxy->mode != PR_MODE_HTTP) {
8378 int optnum;
8379
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008380 if (curproxy->uri_auth) {
8381 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8382 proxy_type_str(curproxy), curproxy->id);
8383 err_code |= ERR_WARN;
8384 curproxy->uri_auth = NULL;
8385 }
8386
Willy Tarreau87cf5142011-08-19 22:57:24 +02008387 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008388 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8389 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8390 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008391 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008392 }
8393
8394 if (curproxy->options & PR_O_ORGTO) {
8395 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8396 "originalto", proxy_type_str(curproxy), curproxy->id);
8397 err_code |= ERR_WARN;
8398 curproxy->options &= ~PR_O_ORGTO;
8399 }
8400
8401 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8402 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8403 (curproxy->cap & cfg_opts[optnum].cap) &&
8404 (curproxy->options & cfg_opts[optnum].val)) {
8405 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8406 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8407 err_code |= ERR_WARN;
8408 curproxy->options &= ~cfg_opts[optnum].val;
8409 }
8410 }
8411
8412 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8413 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8414 (curproxy->cap & cfg_opts2[optnum].cap) &&
8415 (curproxy->options2 & cfg_opts2[optnum].val)) {
8416 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8417 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8418 err_code |= ERR_WARN;
8419 curproxy->options2 &= ~cfg_opts2[optnum].val;
8420 }
8421 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008422
Willy Tarreau29fbe512015-08-20 19:35:14 +02008423#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008424 if (curproxy->conn_src.bind_hdr_occ) {
8425 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008426 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008427 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008428 err_code |= ERR_WARN;
8429 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008430#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008431 }
8432
Willy Tarreaubaaee002006-06-26 02:48:02 +02008433 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008434 * ensure that we're not cross-dressing a TCP server into HTTP.
8435 */
8436 newsrv = curproxy->srv;
8437 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008438 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008439 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8440 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008441 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008442 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008443
Willy Tarreau0cec3312011-10-31 13:49:26 +01008444 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8445 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8446 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8447 err_code |= ERR_WARN;
8448 }
8449
Willy Tarreauc93cd162014-05-13 15:54:22 +02008450 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008451 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8452 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8453 err_code |= ERR_WARN;
8454 }
8455
Willy Tarreau29fbe512015-08-20 19:35:14 +02008456#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008457 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8458 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008459 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 +01008460 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008461 err_code |= ERR_WARN;
8462 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008463#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008464 newsrv = newsrv->next;
8465 }
8466
Willy Tarreaue42bd962014-09-16 16:21:19 +02008467 /* check if we have a frontend with "tcp-request content" looking at L7
8468 * with no inspect-delay
8469 */
8470 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8471 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008472 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008473 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008474 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008475 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008476 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008477 break;
8478 }
8479
8480 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8481 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8482 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8483 " This means that these rules will randomly find their contents. This can be fixed by"
8484 " setting the tcp-request inspect-delay.\n",
8485 proxy_type_str(curproxy), curproxy->id);
8486 err_code |= ERR_WARN;
8487 }
8488 }
8489
Christopher Fauletd7c91962015-04-30 11:48:27 +02008490 /* Check filter configuration, if any */
8491 cfgerr += flt_check(curproxy);
8492
Willy Tarreauc1a21672009-08-16 22:37:44 +02008493 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008494 if (!curproxy->accept)
8495 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008496
Willy Tarreauc1a21672009-08-16 22:37:44 +02008497 if (curproxy->tcp_req.inspect_delay ||
8498 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008499 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008500
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008501 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008502 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008503 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008504 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008505
8506 /* both TCP and HTTP must check switching rules */
8507 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008508
8509 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008510 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008511 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8512 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008513 if (curproxy->mode == PR_MODE_HTTP) {
8514 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8515 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8516 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008517 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008518 }
8519
8520 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008521 if (curproxy->tcp_req.inspect_delay ||
8522 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8523 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8524
Emeric Brun97679e72010-09-23 17:56:44 +02008525 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8526 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8527
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008528 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008529 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008530 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008531 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008532
8533 /* If the backend does requires RDP cookie persistence, we have to
8534 * enable the corresponding analyser.
8535 */
8536 if (curproxy->options2 & PR_O2_RDPC_PRST)
8537 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008538
8539 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008540 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008541 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8542 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008543 if (curproxy->mode == PR_MODE_HTTP) {
8544 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8545 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8546 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008547 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008548 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008549 }
8550
8551 /***********************************************************/
8552 /* At this point, target names have already been resolved. */
8553 /***********************************************************/
8554
8555 /* Check multi-process mode compatibility */
8556
8557 if (global.nbproc > 1 && global.stats_fe) {
8558 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8559 unsigned long mask;
8560
8561 mask = nbits(global.nbproc);
8562 if (global.stats_fe->bind_proc)
8563 mask &= global.stats_fe->bind_proc;
8564
8565 if (bind_conf->bind_proc)
8566 mask &= bind_conf->bind_proc;
8567
8568 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008569 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008570 break;
8571 }
8572 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8573 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");
8574 }
8575 }
8576
8577 /* Make each frontend inherit bind-process from its listeners when not specified. */
8578 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8579 if (curproxy->bind_proc)
8580 continue;
8581
8582 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8583 unsigned long mask;
8584
Willy Tarreaue428b082015-05-04 21:57:58 +02008585 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008586 curproxy->bind_proc |= mask;
8587 }
8588
8589 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008590 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008591 }
8592
8593 if (global.stats_fe) {
8594 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8595 unsigned long mask;
8596
Willy Tarreaue428b082015-05-04 21:57:58 +02008597 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008598 global.stats_fe->bind_proc |= mask;
8599 }
8600 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008601 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008602 }
8603
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008604 /* propagate bindings from frontends to backends. Don't do it if there
8605 * are any fatal errors as we must not call it with unresolved proxies.
8606 */
8607 if (!cfgerr) {
8608 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8609 if (curproxy->cap & PR_CAP_FE)
8610 propagate_processes(curproxy, NULL);
8611 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008612 }
8613
8614 /* Bind each unbound backend to all processes when not specified. */
8615 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8616 if (curproxy->bind_proc)
8617 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008618 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008619 }
8620
8621 /*******************************************************/
8622 /* At this step, all proxies have a non-null bind_proc */
8623 /*******************************************************/
8624
8625 /* perform the final checks before creating tasks */
8626
8627 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8628 struct listener *listener;
8629 unsigned int next_id;
8630 int nbproc;
8631
David Carliere6c39412015-07-02 07:00:17 +00008632 nbproc = my_popcountl(curproxy->bind_proc & nbits(global.nbproc));
Willy Tarreauc1a21672009-08-16 22:37:44 +02008633
Emeric Brunc52962f2012-11-15 18:28:02 +01008634#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008635 /* Configure SSL for each bind line.
8636 * Note: if configuration fails at some point, the ->ctx member
8637 * remains NULL so that listeners can later detach.
8638 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008639 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008640 int alloc_ctx;
8641
Emeric Brunc52962f2012-11-15 18:28:02 +01008642 if (!bind_conf->is_ssl) {
8643 if (bind_conf->default_ctx) {
8644 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8645 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8646 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008647 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008648 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008649 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008650 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008651 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008652 cfgerr++;
8653 continue;
8654 }
8655
Emeric Brun8dc60392014-05-09 13:52:00 +02008656 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008657 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008658 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8659 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");
8660 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008661 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008662 cfgerr++;
8663 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008664 }
8665
Emeric Brunfc0421f2012-09-07 17:30:07 +02008666 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008667 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008668
8669 /* initialize CA variables if the certificates generation is enabled */
8670 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008671 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008672#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008673
Willy Tarreaue6b98942007-10-29 01:09:36 +01008674 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008675 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008676 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008677 if (!listener->luid) {
8678 /* listener ID not set, use automatic numbering with first
8679 * spare entry starting with next_luid.
8680 */
8681 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8682 listener->conf.id.key = listener->luid = next_id;
8683 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008684 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008685 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008686
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008687 /* enable separate counters */
8688 if (curproxy->options2 & PR_O2_SOCKSTAT) {
8689 listener->counters = (struct licounters *)calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008690 if (!listener->name)
8691 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008692 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008693
Willy Tarreaue6b98942007-10-29 01:09:36 +01008694 if (curproxy->options & PR_O_TCP_NOLING)
8695 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008696 if (!listener->maxconn)
8697 listener->maxconn = curproxy->maxconn;
8698 if (!listener->backlog)
8699 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008700 if (!listener->maxaccept)
8701 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8702
8703 /* we want to have an optimal behaviour on single process mode to
8704 * maximize the work at once, but in multi-process we want to keep
8705 * some fairness between processes, so we target half of the max
8706 * number of events to be balanced over all the processes the proxy
8707 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8708 * used to disable the limit.
8709 */
8710 if (listener->maxaccept > 0) {
8711 if (nbproc > 1)
8712 listener->maxaccept = (listener->maxaccept + 1) / 2;
8713 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8714 }
8715
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008716 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008717 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008718 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008719 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008720
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008721 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8722 listener->options |= LI_O_TCP_RULES;
8723
Willy Tarreaude3041d2010-05-31 10:56:17 +02008724 if (curproxy->mon_mask.s_addr)
8725 listener->options |= LI_O_CHK_MONNET;
8726
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008727 /* smart accept mode is automatic in HTTP mode */
8728 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008729 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008730 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8731 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008732 }
8733
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008734 /* Release unused SSL configs */
8735 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8736 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008737 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008738#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008739 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008740 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008741 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008742 free(bind_conf->ca_sign_file);
8743 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008744 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008745 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008746 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008747 if(bind_conf->keys_ref) {
8748 free(bind_conf->keys_ref->filename);
8749 free(bind_conf->keys_ref->tlskeys);
8750 free(bind_conf->keys_ref);
8751 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008752#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008753 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008754
Willy Tarreau102df612014-05-07 23:56:38 +02008755 if (nbproc > 1) {
8756 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008757 int count, maxproc = 0;
8758
8759 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008760 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008761 if (count > maxproc)
8762 maxproc = count;
8763 }
8764 /* backends have 0, frontends have 1 or more */
8765 if (maxproc != 1)
8766 Warning("Proxy '%s': in multi-process mode, stats will be"
8767 " limited to process assigned to the current request.\n",
8768 curproxy->id);
8769
Willy Tarreau102df612014-05-07 23:56:38 +02008770 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8771 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8772 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008773 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008774 }
Willy Tarreau102df612014-05-07 23:56:38 +02008775 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8776 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8777 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008778 }
8779 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008780
8781 /* create the task associated with the proxy */
8782 curproxy->task = task_new();
8783 if (curproxy->task) {
8784 curproxy->task->context = curproxy;
8785 curproxy->task->process = manage_proxy;
8786 /* no need to queue, it will be done automatically if some
8787 * listener gets limited.
8788 */
8789 curproxy->task->expire = TICK_ETERNITY;
8790 } else {
8791 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8792 curproxy->id);
8793 cfgerr++;
8794 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008795 }
8796
Willy Tarreaufbb78422011-06-05 15:38:35 +02008797 /* automatically compute fullconn if not set. We must not do it in the
8798 * loop above because cross-references are not yet fully resolved.
8799 */
8800 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8801 /* If <fullconn> is not set, let's set it to 10% of the sum of
8802 * the possible incoming frontend's maxconns.
8803 */
8804 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8805 struct proxy *fe;
8806 int total = 0;
8807
8808 /* sum up the number of maxconns of frontends which
8809 * reference this backend at least once or which are
8810 * the same one ('listen').
8811 */
8812 for (fe = proxy; fe; fe = fe->next) {
8813 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008814 int found = 0;
8815
8816 if (!(fe->cap & PR_CAP_FE))
8817 continue;
8818
8819 if (fe == curproxy) /* we're on a "listen" instance */
8820 found = 1;
8821
8822 if (fe->defbe.be == curproxy) /* "default_backend" */
8823 found = 1;
8824
8825 /* check if a "use_backend" rule matches */
8826 if (!found) {
8827 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008828 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008829 found = 1;
8830 break;
8831 }
8832 }
8833 }
8834
Willy Tarreaufbb78422011-06-05 15:38:35 +02008835 /* now we've checked all possible ways to reference a backend
8836 * from a frontend.
8837 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008838 if (!found)
8839 continue;
8840 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008841 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008842 /* we have the sum of the maxconns in <total>. We only
8843 * keep 10% of that sum to set the default fullconn, with
8844 * a hard minimum of 1 (to avoid a divide by zero).
8845 */
8846 curproxy->fullconn = (total + 9) / 10;
8847 if (!curproxy->fullconn)
8848 curproxy->fullconn = 1;
8849 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008850 }
8851
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008852 /*
8853 * Recount currently required checks.
8854 */
8855
8856 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8857 int optnum;
8858
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008859 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8860 if (curproxy->options & cfg_opts[optnum].val)
8861 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008862
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008863 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8864 if (curproxy->options2 & cfg_opts2[optnum].val)
8865 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008866 }
8867
Willy Tarreau0fca4832015-05-01 19:12:05 +02008868 /* compute the required process bindings for the peers */
8869 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8870 if (curproxy->table.peers.p)
8871 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8872
Willy Tarreau122541c2011-09-07 21:24:49 +02008873 if (peers) {
8874 struct peers *curpeers = peers, **last;
8875 struct peer *p, *pb;
8876
Willy Tarreau1e273012015-05-01 19:15:17 +02008877 /* Remove all peers sections which don't have a valid listener,
8878 * which are not used by any table, or which are bound to more
8879 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008880 */
8881 last = &peers;
8882 while (*last) {
8883 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008884
8885 if (curpeers->state == PR_STSTOPPED) {
8886 /* the "disabled" keyword was present */
8887 if (curpeers->peers_fe)
8888 stop_proxy(curpeers->peers_fe);
8889 curpeers->peers_fe = NULL;
8890 }
8891 else if (!curpeers->peers_fe) {
8892 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8893 curpeers->id, localpeer);
8894 }
David Carliere6c39412015-07-02 07:00:17 +00008895 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02008896 /* either it's totally stopped or too much used */
8897 if (curpeers->peers_fe->bind_proc) {
8898 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02008899 "running in different processes (%d different ones). "
8900 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00008901 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02008902 cfgerr++;
8903 }
8904 stop_proxy(curpeers->peers_fe);
8905 curpeers->peers_fe = NULL;
8906 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008907 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02008908 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02008909 last = &curpeers->next;
8910 continue;
8911 }
8912
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008913 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02008914 p = curpeers->remote;
8915 while (p) {
8916 pb = p->next;
8917 free(p->id);
8918 free(p);
8919 p = pb;
8920 }
8921
8922 /* Destroy and unlink this curpeers section.
8923 * Note: curpeers is backed up into *last.
8924 */
8925 free(curpeers->id);
8926 curpeers = curpeers->next;
8927 free(*last);
8928 *last = curpeers;
8929 }
8930 }
8931
Willy Tarreau6866f3f2015-05-01 19:09:08 +02008932 /* initialize stick-tables on backend capable proxies. This must not
8933 * be done earlier because the data size may be discovered while parsing
8934 * other proxies.
8935 */
8936 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8937 if (curproxy->state == PR_STSTOPPED)
8938 continue;
8939
8940 if (!stktable_init(&curproxy->table)) {
8941 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
8942 cfgerr++;
8943 }
8944 }
8945
Simon Horman0d16a402015-01-30 11:22:58 +09008946 if (mailers) {
8947 struct mailers *curmailers = mailers, **last;
8948 struct mailer *m, *mb;
8949
8950 /* Remove all mailers sections which don't have a valid listener.
8951 * This can happen when a mailers section is never referenced.
8952 */
8953 last = &mailers;
8954 while (*last) {
8955 curmailers = *last;
8956 if (curmailers->users) {
8957 last = &curmailers->next;
8958 continue;
8959 }
8960
8961 Warning("Removing incomplete section 'mailers %s'.\n",
8962 curmailers->id);
8963
8964 m = curmailers->mailer_list;
8965 while (m) {
8966 mb = m->next;
8967 free(m->id);
8968 free(m);
8969 m = mb;
8970 }
8971
8972 /* Destroy and unlink this curmailers section.
8973 * Note: curmailers is backed up into *last.
8974 */
8975 free(curmailers->id);
8976 curmailers = curmailers->next;
8977 free(*last);
8978 *last = curmailers;
8979 }
8980 }
8981
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008982 /* Update server_state_file_name to backend name if backend is supposed to use
8983 * a server-state file locally defined and none has been provided */
8984 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8985 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
8986 curproxy->server_state_file_name == NULL)
8987 curproxy->server_state_file_name = strdup(curproxy->id);
8988 }
8989
Willy Tarreau34eb6712011-10-24 18:15:04 +02008990 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02008991 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02008992 MEM_F_SHARED);
8993
Willy Tarreaubb925012009-07-23 13:36:36 +02008994 if (cfgerr > 0)
8995 err_code |= ERR_ALERT | ERR_FATAL;
8996 out:
8997 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02008998}
8999
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009000/*
9001 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9002 * parsing sessions.
9003 */
9004void cfg_register_keywords(struct cfg_kw_list *kwl)
9005{
9006 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9007}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009008
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009009/*
9010 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9011 */
9012void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9013{
9014 LIST_DEL(&kwl->list);
9015 LIST_INIT(&kwl->list);
9016}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009017
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009018/* this function register new section in the haproxy configuration file.
9019 * <section_name> is the name of this new section and <section_parser>
9020 * is the called parser. If two section declaration have the same name,
9021 * only the first declared is used.
9022 */
9023int cfg_register_section(char *section_name,
9024 int (*section_parser)(const char *, int, char **, int))
9025{
9026 struct cfg_section *cs;
9027
9028 cs = calloc(1, sizeof(*cs));
9029 if (!cs) {
9030 Alert("register section '%s': out of memory.\n", section_name);
9031 return 0;
9032 }
9033
9034 cs->section_name = section_name;
9035 cs->section_parser = section_parser;
9036
9037 LIST_ADDQ(&sections, &cs->list);
9038
9039 return 1;
9040}
9041
Willy Tarreaubaaee002006-06-26 02:48:02 +02009042/*
David Carlier845efb52015-09-25 11:49:18 +01009043 * free all config section entries
9044 */
9045void cfg_unregister_sections(void)
9046{
9047 struct cfg_section *cs, *ics;
9048
9049 list_for_each_entry_safe(cs, ics, &sections, list) {
9050 LIST_DEL(&cs->list);
9051 free(cs);
9052 }
9053}
9054
9055/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009056 * Local variables:
9057 * c-indent-level: 8
9058 * c-basic-offset: 8
9059 * End:
9060 */