blob: 09077d8ced2d0874a02dd5a7f7a6acb55bf3fb7b [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 */
Vincent Bernat6e615892016-05-18 16:17:44 +0200290 memcpy(&ss, ss2, sizeof(ss));
Willy Tarreau12eb2a62013-03-06 15:45:03 +0100291
Willy Tarreaubaaee002006-06-26 02:48:02 +0200292 for (; port <= end; port++) {
Vincent Bernat02779b62016-04-03 13:48:43 +0200293 l = calloc(1, sizeof(*l));
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;
Vincent Bernat6e46ff12016-05-19 11:29:43 +0200301 memcpy(&l->addr, &ss, sizeof(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 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001078 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1079 Warning("parsing [%s:%d] : uid: string '%s' is not a number.\n | You might want to use the 'user' parameter to use a system user name.\n", file, linenum, args[1]);
1080 err_code |= ERR_WARN;
1081 goto out;
1082 }
1083
Willy Tarreaubaaee002006-06-26 02:48:02 +02001084 }
1085 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001086 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1087 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001088 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001089 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001090 err_code |= ERR_ALERT;
1091 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001092 }
1093 if (*(args[1]) == 0) {
1094 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001095 err_code |= ERR_ALERT | ERR_FATAL;
1096 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001097 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001098 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1099 Warning("parsing [%s:%d] : gid: string '%s' is not a number.\n | You might want to use the 'group' parameter to use a system group name.\n", file, linenum, args[1]);
1100 err_code |= ERR_WARN;
1101 goto out;
1102 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
Simon Horman98637e52014-06-20 12:30:16 +09001104 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001105 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1106 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001107 global.external_check = 1;
1108 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001109 /* user/group name handling */
1110 else if (!strcmp(args[0], "user")) {
1111 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001112 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1113 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001114 if (global.uid != 0) {
1115 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001116 err_code |= ERR_ALERT;
1117 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001118 }
1119 errno = 0;
1120 ha_user = getpwnam(args[1]);
1121 if (ha_user != NULL) {
1122 global.uid = (int)ha_user->pw_uid;
1123 }
1124 else {
1125 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 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001127 }
1128 }
1129 else if (!strcmp(args[0], "group")) {
1130 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001131 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1132 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001133 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001134 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001135 err_code |= ERR_ALERT;
1136 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001137 }
1138 errno = 0;
1139 ha_group = getgrnam(args[1]);
1140 if (ha_group != NULL) {
1141 global.gid = (int)ha_group->gr_gid;
1142 }
1143 else {
1144 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 +02001145 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001146 }
1147 }
1148 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001149 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001150 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1151 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001152 if (*(args[1]) == 0) {
1153 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001154 err_code |= ERR_ALERT | ERR_FATAL;
1155 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001156 }
1157 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001158 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1159 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1160 file, linenum, args[0], LONGBITS, global.nbproc);
1161 err_code |= ERR_ALERT | ERR_FATAL;
1162 goto out;
1163 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001164 }
1165 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001166 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1167 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001168 if (global.maxconn != 0) {
1169 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001170 err_code |= ERR_ALERT;
1171 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001172 }
1173 if (*(args[1]) == 0) {
1174 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001175 err_code |= ERR_ALERT | ERR_FATAL;
1176 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001177 }
1178 global.maxconn = atol(args[1]);
1179#ifdef SYSTEM_MAXCONN
1180 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1181 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);
1182 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001183 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001184 }
1185#endif /* SYSTEM_MAXCONN */
1186 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001187 else if (!strcmp(args[0], "maxsslconn")) {
1188#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001189 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1190 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001191 if (*(args[1]) == 0) {
1192 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1193 err_code |= ERR_ALERT | ERR_FATAL;
1194 goto out;
1195 }
1196 global.maxsslconn = atol(args[1]);
1197#else
Emeric Brun0914df82012-10-02 18:45:42 +02001198 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1199 err_code |= ERR_ALERT | ERR_FATAL;
1200 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001201#endif
1202 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001203 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1204#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001205 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1206 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001207 if (*(args[1]) == 0) {
1208 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1209 err_code |= ERR_ALERT | ERR_FATAL;
1210 goto out;
1211 }
1212 free(global.listen_default_ciphers);
1213 global.listen_default_ciphers = strdup(args[1]);
1214#else
1215 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1216 err_code |= ERR_ALERT | ERR_FATAL;
1217 goto out;
1218#endif
1219 }
1220 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1221#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001222 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1223 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001224 if (*(args[1]) == 0) {
1225 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1226 err_code |= ERR_ALERT | ERR_FATAL;
1227 goto out;
1228 }
1229 free(global.connect_default_ciphers);
1230 global.connect_default_ciphers = strdup(args[1]);
1231#else
1232 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1233 err_code |= ERR_ALERT | ERR_FATAL;
1234 goto out;
1235#endif
1236 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001237#ifdef USE_OPENSSL
1238#ifndef OPENSSL_NO_DH
1239 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1240 if (*(args[1]) == 0) {
1241 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1242 err_code |= ERR_ALERT | ERR_FATAL;
1243 goto out;
1244 }
1245 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1246 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249 }
1250 }
1251#endif
1252#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001253 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1255 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001256 if (*(args[1]) == 0) {
1257 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1258 err_code |= ERR_ALERT | ERR_FATAL;
1259 goto out;
1260 }
1261 if (strcmp(args[1],"none") == 0)
1262 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1263 else if (strcmp(args[1],"required") == 0)
1264 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1265 else {
1266 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1267 err_code |= ERR_ALERT | ERR_FATAL;
1268 goto out;
1269 }
1270 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001271 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001272 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1273 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001274 if (global.cps_lim != 0) {
1275 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1276 err_code |= ERR_ALERT;
1277 goto out;
1278 }
1279 if (*(args[1]) == 0) {
1280 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1281 err_code |= ERR_ALERT | ERR_FATAL;
1282 goto out;
1283 }
1284 global.cps_lim = atol(args[1]);
1285 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001286 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001287 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1288 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001289 if (global.sps_lim != 0) {
1290 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1291 err_code |= ERR_ALERT;
1292 goto out;
1293 }
1294 if (*(args[1]) == 0) {
1295 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1296 err_code |= ERR_ALERT | ERR_FATAL;
1297 goto out;
1298 }
1299 global.sps_lim = atol(args[1]);
1300 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001301 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001302 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1303 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001304 if (global.ssl_lim != 0) {
1305 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1306 err_code |= ERR_ALERT;
1307 goto out;
1308 }
1309 if (*(args[1]) == 0) {
1310 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1311 err_code |= ERR_ALERT | ERR_FATAL;
1312 goto out;
1313 }
1314 global.ssl_lim = atol(args[1]);
1315 }
William Lallemandd85f9172012-11-09 17:05:39 +01001316 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001317 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1318 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001319 if (*(args[1]) == 0) {
1320 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1321 err_code |= ERR_ALERT | ERR_FATAL;
1322 goto out;
1323 }
1324 global.comp_rate_lim = atoi(args[1]) * 1024;
1325 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001326 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001327 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1328 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001329 if (global.maxpipes != 0) {
1330 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001331 err_code |= ERR_ALERT;
1332 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001333 }
1334 if (*(args[1]) == 0) {
1335 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001336 err_code |= ERR_ALERT | ERR_FATAL;
1337 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001338 }
1339 global.maxpipes = atol(args[1]);
1340 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001341 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001342 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1343 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001344 if (*(args[1]) == 0) {
1345 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1346 err_code |= ERR_ALERT | ERR_FATAL;
1347 goto out;
1348 }
William Lallemande3a7d992012-11-20 11:25:20 +01001349 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001350 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001351 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001352 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1353 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001354 if (*(args[1]) == 0) {
1355 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1356 err_code |= ERR_ALERT | ERR_FATAL;
1357 goto out;
1358 }
1359 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001360 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001361 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1362 err_code |= ERR_ALERT | ERR_FATAL;
1363 goto out;
1364 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001365 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001366
Willy Tarreaubaaee002006-06-26 02:48:02 +02001367 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001368 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1369 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001370 if (global.rlimit_nofile != 0) {
1371 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001372 err_code |= ERR_ALERT;
1373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001374 }
1375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001379 }
1380 global.rlimit_nofile = atol(args[1]);
1381 }
1382 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001383 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1384 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001385 if (global.chroot != NULL) {
1386 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001387 err_code |= ERR_ALERT;
1388 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001389 }
1390 if (*(args[1]) == 0) {
1391 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001392 err_code |= ERR_ALERT | ERR_FATAL;
1393 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001394 }
1395 global.chroot = strdup(args[1]);
1396 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001397 else if (!strcmp(args[0], "description")) {
1398 int i, len=0;
1399 char *d;
1400
1401 if (!*args[1]) {
1402 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1403 file, linenum, args[0]);
1404 err_code |= ERR_ALERT | ERR_FATAL;
1405 goto out;
1406 }
1407
Willy Tarreau348acfe2014-04-14 15:00:39 +02001408 for (i = 1; *args[i]; i++)
1409 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001410
1411 if (global.desc)
1412 free(global.desc);
1413
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001414 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001415
Willy Tarreau348acfe2014-04-14 15:00:39 +02001416 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1417 for (i = 2; *args[i]; i++)
1418 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001419 }
1420 else if (!strcmp(args[0], "node")) {
1421 int i;
1422 char c;
1423
William Lallemand1a748ae2015-05-19 16:37:23 +02001424 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1425 goto out;
1426
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001427 for (i=0; args[1][i]; i++) {
1428 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001429 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1430 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001431 break;
1432 }
1433
1434 if (!i || args[1][i]) {
1435 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1436 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1437 file, linenum, args[0]);
1438 err_code |= ERR_ALERT | ERR_FATAL;
1439 goto out;
1440 }
1441
1442 if (global.node)
1443 free(global.node);
1444
1445 global.node = strdup(args[1]);
1446 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001447 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001448 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1449 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001450 if (global.pidfile != NULL) {
1451 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001452 err_code |= ERR_ALERT;
1453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001454 }
1455 if (*(args[1]) == 0) {
1456 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001457 err_code |= ERR_ALERT | ERR_FATAL;
1458 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001459 }
1460 global.pidfile = strdup(args[1]);
1461 }
Emeric Bruned760922010-10-22 17:59:25 +02001462 else if (!strcmp(args[0], "unix-bind")) {
1463 int cur_arg = 1;
1464 while (*(args[cur_arg])) {
1465 if (!strcmp(args[cur_arg], "prefix")) {
1466 if (global.unix_bind.prefix != NULL) {
1467 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1468 err_code |= ERR_ALERT;
1469 cur_arg += 2;
1470 continue;
1471 }
1472
1473 if (*(args[cur_arg+1]) == 0) {
1474 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1475 err_code |= ERR_ALERT | ERR_FATAL;
1476 goto out;
1477 }
1478 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1479 cur_arg += 2;
1480 continue;
1481 }
1482
1483 if (!strcmp(args[cur_arg], "mode")) {
1484
1485 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1486 cur_arg += 2;
1487 continue;
1488 }
1489
1490 if (!strcmp(args[cur_arg], "uid")) {
1491
1492 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1493 cur_arg += 2;
1494 continue;
1495 }
1496
1497 if (!strcmp(args[cur_arg], "gid")) {
1498
1499 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1500 cur_arg += 2;
1501 continue;
1502 }
1503
1504 if (!strcmp(args[cur_arg], "user")) {
1505 struct passwd *user;
1506
1507 user = getpwnam(args[cur_arg + 1]);
1508 if (!user) {
1509 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1510 file, linenum, args[0], args[cur_arg + 1 ]);
1511 err_code |= ERR_ALERT | ERR_FATAL;
1512 goto out;
1513 }
1514
1515 global.unix_bind.ux.uid = user->pw_uid;
1516 cur_arg += 2;
1517 continue;
1518 }
1519
1520 if (!strcmp(args[cur_arg], "group")) {
1521 struct group *group;
1522
1523 group = getgrnam(args[cur_arg + 1]);
1524 if (!group) {
1525 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1526 file, linenum, args[0], args[cur_arg + 1 ]);
1527 err_code |= ERR_ALERT | ERR_FATAL;
1528 goto out;
1529 }
1530
1531 global.unix_bind.ux.gid = group->gr_gid;
1532 cur_arg += 2;
1533 continue;
1534 }
1535
Willy Tarreaub48f9582011-09-05 01:17:06 +02001536 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001537 file, linenum, args[0]);
1538 err_code |= ERR_ALERT | ERR_FATAL;
1539 goto out;
1540 }
1541 }
William Lallemand0f99e342011-10-12 17:50:54 +02001542 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1543 /* delete previous herited or defined syslog servers */
1544 struct logsrv *back;
1545 struct logsrv *tmp;
1546
1547 if (*(args[1]) != 0) {
1548 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1549 err_code |= ERR_ALERT | ERR_FATAL;
1550 goto out;
1551 }
1552
1553 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1554 LIST_DEL(&tmp->list);
1555 free(tmp);
1556 }
1557 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001558 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001559 struct sockaddr_storage *sk;
1560 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001561 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001562 int arg = 0;
1563 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001564
William Lallemand1a748ae2015-05-19 16:37:23 +02001565 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1566 goto out;
1567
Willy Tarreaubaaee002006-06-26 02:48:02 +02001568 if (*(args[1]) == 0 || *(args[2]) == 0) {
1569 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001570 err_code |= ERR_ALERT | ERR_FATAL;
1571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001572 }
William Lallemand0f99e342011-10-12 17:50:54 +02001573
Vincent Bernat02779b62016-04-03 13:48:43 +02001574 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001575
Willy Tarreau18324f52014-06-27 18:10:07 +02001576 /* just after the address, a length may be specified */
1577 if (strcmp(args[arg+2], "len") == 0) {
1578 len = atoi(args[arg+3]);
1579 if (len < 80 || len > 65535) {
1580 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1581 file, linenum, args[arg+3]);
1582 err_code |= ERR_ALERT | ERR_FATAL;
1583 goto out;
1584 }
1585 logsrv->maxlen = len;
1586
1587 /* skip these two args */
1588 arg += 2;
1589 }
1590 else
1591 logsrv->maxlen = MAX_SYSLOG_LEN;
1592
1593 if (logsrv->maxlen > global.max_syslog_len) {
1594 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001595 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1596 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1597 logline = my_realloc2(logline, global.max_syslog_len + 1);
1598 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001599 }
1600
Dragan Dosen1322d092015-09-22 16:05:32 +02001601 /* after the length, a format may be specified */
1602 if (strcmp(args[arg+2], "format") == 0) {
1603 logsrv->format = get_log_format(args[arg+3]);
1604 if (logsrv->format < 0) {
1605 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1606 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001607 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001608 goto out;
1609 }
1610
1611 /* skip these two args */
1612 arg += 2;
1613 }
1614
David Carlier97880bb2016-04-08 10:35:26 +01001615 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1616 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001617 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001618 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001619
Willy Tarreau18324f52014-06-27 18:10:07 +02001620 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001621 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001622 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001623 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001624 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001625 }
1626
William Lallemand0f99e342011-10-12 17:50:54 +02001627 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001628 if (*(args[arg+3])) {
1629 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001630 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001631 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001632 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001633 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001634 }
1635 }
1636
William Lallemand0f99e342011-10-12 17:50:54 +02001637 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001638 if (*(args[arg+4])) {
1639 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001640 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001641 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001642 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001643 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001644 }
1645 }
1646
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001647 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001648 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001649 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001650 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001651 free(logsrv);
1652 goto out;
1653 }
1654 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001655
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001656 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001657 if (port1 != port2) {
1658 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1659 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001660 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001661 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001662 goto out;
1663 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001664
William Lallemand0f99e342011-10-12 17:50:54 +02001665 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001666 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001667 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001668 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001669
William Lallemand0f99e342011-10-12 17:50:54 +02001670 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001671 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001672 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1673 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001674
1675 if (global.log_send_hostname != NULL) {
1676 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1677 err_code |= ERR_ALERT;
1678 goto out;
1679 }
1680
1681 if (*(args[1]))
1682 name = args[1];
1683 else
1684 name = hostname;
1685
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001686 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001687 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001688 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001689 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1690 if (global.server_state_base != NULL) {
1691 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1692 err_code |= ERR_ALERT;
1693 goto out;
1694 }
1695
1696 if (!*(args[1])) {
1697 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1698 err_code |= ERR_FATAL;
1699 goto out;
1700 }
1701
1702 global.server_state_base = strdup(args[1]);
1703 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001704 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1705 if (global.server_state_file != NULL) {
1706 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1707 err_code |= ERR_ALERT;
1708 goto out;
1709 }
1710
1711 if (!*(args[1])) {
1712 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1713 err_code |= ERR_FATAL;
1714 goto out;
1715 }
1716
1717 global.server_state_file = strdup(args[1]);
1718 }
Kevinm48936af2010-12-22 16:08:21 +00001719 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001720 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1721 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001722 if (*(args[1]) == 0) {
1723 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1724 err_code |= ERR_ALERT | ERR_FATAL;
1725 goto out;
1726 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001727 chunk_destroy(&global.log_tag);
1728 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001729 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001730 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001731 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1732 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001733 if (global.spread_checks != 0) {
1734 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001735 err_code |= ERR_ALERT;
1736 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001737 }
1738 if (*(args[1]) == 0) {
1739 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001740 err_code |= ERR_ALERT | ERR_FATAL;
1741 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001742 }
1743 global.spread_checks = atol(args[1]);
1744 if (global.spread_checks < 0 || global.spread_checks > 50) {
1745 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001746 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001747 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001748 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001749 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1750 const char *err;
1751 unsigned int val;
1752
William Lallemand1a748ae2015-05-19 16:37:23 +02001753 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1754 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001755 if (*(args[1]) == 0) {
1756 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1757 err_code |= ERR_ALERT | ERR_FATAL;
1758 goto out;
1759 }
1760
1761 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1762 if (err) {
1763 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1764 err_code |= ERR_ALERT | ERR_FATAL;
1765 }
1766 global.max_spread_checks = val;
1767 if (global.max_spread_checks < 0) {
1768 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1769 err_code |= ERR_ALERT | ERR_FATAL;
1770 }
1771 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001772 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1773#ifdef USE_CPU_AFFINITY
1774 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001775 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001776 unsigned long cpus = 0;
1777
1778 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001779 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001780 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001781 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001782 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001783 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001784 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001785 proc = atol(args[1]);
1786 if (proc >= 1 && proc <= LONGBITS)
1787 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001788 }
1789
1790 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001791 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",
1792 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001793 err_code |= ERR_ALERT | ERR_FATAL;
1794 goto out;
1795 }
1796
1797 cur_arg = 2;
1798 while (*args[cur_arg]) {
1799 unsigned int low, high;
1800
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001801 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001802 char *dash = strchr(args[cur_arg], '-');
1803
1804 low = high = str2uic(args[cur_arg]);
1805 if (dash)
1806 high = str2uic(dash + 1);
1807
1808 if (high < low) {
1809 unsigned int swap = low;
1810 low = high;
1811 high = swap;
1812 }
1813
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001814 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001815 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001816 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001817 err_code |= ERR_ALERT | ERR_FATAL;
1818 goto out;
1819 }
1820
1821 while (low <= high)
1822 cpus |= 1UL << low++;
1823 }
1824 else {
1825 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1826 file, linenum, args[0], args[cur_arg]);
1827 err_code |= ERR_ALERT | ERR_FATAL;
1828 goto out;
1829 }
1830 cur_arg++;
1831 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001832 for (i = 0; i < LONGBITS; i++)
1833 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001834 global.cpu_map[i] = cpus;
1835#else
1836 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1837 err_code |= ERR_ALERT | ERR_FATAL;
1838 goto out;
1839#endif
1840 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001841 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1842 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1843 goto out;
1844
1845 if (*(args[2]) == 0) {
1846 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1847 err_code |= ERR_ALERT | ERR_FATAL;
1848 goto out;
1849 }
1850
1851 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1852 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1853 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1854 err_code |= ERR_ALERT | ERR_FATAL;
1855 goto out;
1856 }
1857 }
1858 else if (!strcmp(args[0], "unsetenv")) {
1859 int arg;
1860
1861 if (*(args[1]) == 0) {
1862 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1863 err_code |= ERR_ALERT | ERR_FATAL;
1864 goto out;
1865 }
1866
1867 for (arg = 1; *args[arg]; arg++) {
1868 if (unsetenv(args[arg]) != 0) {
1869 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1870 err_code |= ERR_ALERT | ERR_FATAL;
1871 goto out;
1872 }
1873 }
1874 }
1875 else if (!strcmp(args[0], "resetenv")) {
1876 extern char **environ;
1877 char **env = environ;
1878
1879 /* args contain variable names to keep, one per argument */
1880 while (*env) {
1881 int arg;
1882
1883 /* look for current variable in among all those we want to keep */
1884 for (arg = 1; *args[arg]; arg++) {
1885 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1886 (*env)[strlen(args[arg])] == '=')
1887 break;
1888 }
1889
1890 /* delete this variable */
1891 if (!*args[arg]) {
1892 char *delim = strchr(*env, '=');
1893
1894 if (!delim || delim - *env >= trash.size) {
1895 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1896 err_code |= ERR_ALERT | ERR_FATAL;
1897 goto out;
1898 }
1899
1900 memcpy(trash.str, *env, delim - *env);
1901 trash.str[delim - *env] = 0;
1902
1903 if (unsetenv(trash.str) != 0) {
1904 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1905 err_code |= ERR_ALERT | ERR_FATAL;
1906 goto out;
1907 }
1908 }
1909 else
1910 env++;
1911 }
1912 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001913 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001914 struct cfg_kw_list *kwl;
1915 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001916 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001917
1918 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1919 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1920 if (kwl->kw[index].section != CFG_GLOBAL)
1921 continue;
1922 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001923 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001924 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001925 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001926 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001927 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001928 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001929 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001930 err_code |= ERR_WARN;
1931 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001932 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001933 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001934 }
1935 }
1936 }
1937
Willy Tarreaubaaee002006-06-26 02:48:02 +02001938 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001939 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001940 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001941
Willy Tarreau058e9072009-07-20 09:30:05 +02001942 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001943 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001944 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001945}
1946
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001947void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001948{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001949 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001950 defproxy.mode = PR_MODE_TCP;
1951 defproxy.state = PR_STNEW;
1952 defproxy.maxconn = cfg_maxpconn;
1953 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001954 defproxy.redispatch_after = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001955
Simon Horman66183002013-02-23 10:16:43 +09001956 defproxy.defsrv.check.inter = DEF_CHKINTR;
1957 defproxy.defsrv.check.fastinter = 0;
1958 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001959 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1960 defproxy.defsrv.agent.fastinter = 0;
1961 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001962 defproxy.defsrv.check.rise = DEF_RISETIME;
1963 defproxy.defsrv.check.fall = DEF_FALLTIME;
1964 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1965 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001966 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001967 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001968 defproxy.defsrv.maxqueue = 0;
1969 defproxy.defsrv.minconn = 0;
1970 defproxy.defsrv.maxconn = 0;
1971 defproxy.defsrv.slowstart = 0;
1972 defproxy.defsrv.onerror = DEF_HANA_ONERR;
1973 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
1974 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09001975
1976 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02001977 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001978}
1979
Willy Tarreauade5ec42010-01-28 19:33:49 +01001980
Willy Tarreau63af98d2014-05-18 08:11:41 +02001981/* This function createss a new req* or rsp* rule to the proxy. It compiles the
1982 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
1983 * ERR_FATAL in case of error.
1984 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01001985static int create_cond_regex_rule(const char *file, int line,
1986 struct proxy *px, int dir, int action, int flags,
1987 const char *cmd, const char *reg, const char *repl,
1988 const char **cond_start)
1989{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001990 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02001991 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001992 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001993 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02001994 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01001995 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02001996 int cs;
1997 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01001998
1999 if (px == &defproxy) {
2000 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002001 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002002 goto err;
2003 }
2004
2005 if (*reg == 0) {
2006 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002007 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002008 goto err;
2009 }
2010
2011 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002012 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002013
Willy Tarreau5321c422010-01-28 20:35:13 +01002014 if (cond_start &&
2015 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002016 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2017 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2018 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002019 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002020 goto err;
2021 }
2022 }
2023 else if (cond_start && **cond_start) {
2024 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2025 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002026 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002027 goto err;
2028 }
2029
Willy Tarreau63af98d2014-05-18 08:11:41 +02002030 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002031 (dir == SMP_OPT_DIR_REQ) ?
2032 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2033 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2034 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002035
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002036 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002037 if (!preg) {
2038 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002039 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002040 goto err;
2041 }
2042
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002043 cs = !(flags & REG_ICASE);
2044 cap = !(flags & REG_NOSUB);
2045 error = NULL;
2046 if (!regex_comp(reg, preg, cs, cap, &error)) {
2047 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2048 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002049 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002050 goto err;
2051 }
2052
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002053 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002054 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002055 if (repl && err) {
2056 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2057 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002058 ret_code |= ERR_ALERT | ERR_FATAL;
2059 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002060 }
2061
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002062 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002063 ret_code |= ERR_WARN;
2064
2065 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002066
Willy Tarreau63af98d2014-05-18 08:11:41 +02002067 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002068 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002069 err:
2070 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002071 free(errmsg);
2072 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002073}
2074
Willy Tarreaubaaee002006-06-26 02:48:02 +02002075/*
William Lallemand51097192015-04-14 16:35:22 +02002076 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002077 * Returns the error code, 0 if OK, or any combination of :
2078 * - ERR_ABORT: must abort ASAP
2079 * - ERR_FATAL: we can continue parsing but not start the service
2080 * - ERR_WARN: a warning has been emitted
2081 * - ERR_ALERT: an alert has been emitted
2082 * Only the two first ones can stop processing, the two others are just
2083 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002084 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002085int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2086{
2087 static struct peers *curpeers = NULL;
2088 struct peer *newpeer = NULL;
2089 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002090 struct bind_conf *bind_conf;
2091 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002092 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002093 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002094
2095 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002096 if (!*args[1]) {
2097 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002098 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002099 goto out;
2100 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002101
William Lallemand6e62fb62015-04-28 16:55:23 +02002102 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2103 goto out;
2104
Emeric Brun32da3c42010-09-23 18:39:19 +02002105 err = invalid_char(args[1]);
2106 if (err) {
2107 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2108 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002109 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002110 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002111 }
2112
2113 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2114 /*
2115 * If there are two proxies with the same name only following
2116 * combinations are allowed:
2117 */
2118 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002119 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 +02002120 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002121 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002122 }
2123 }
2124
Vincent Bernat02779b62016-04-03 13:48:43 +02002125 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002126 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2127 err_code |= ERR_ALERT | ERR_ABORT;
2128 goto out;
2129 }
2130
2131 curpeers->next = peers;
2132 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002133 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002134 curpeers->conf.line = linenum;
2135 curpeers->last_change = now.tv_sec;
2136 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002137 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002138 }
2139 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002140 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002141 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002142 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002143
2144 if (!*args[2]) {
2145 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2146 file, linenum, args[0]);
2147 err_code |= ERR_ALERT | ERR_FATAL;
2148 goto out;
2149 }
2150
2151 err = invalid_char(args[1]);
2152 if (err) {
2153 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2154 file, linenum, *err, args[1]);
2155 err_code |= ERR_ALERT | ERR_FATAL;
2156 goto out;
2157 }
2158
Vincent Bernat02779b62016-04-03 13:48:43 +02002159 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002160 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2161 err_code |= ERR_ALERT | ERR_ABORT;
2162 goto out;
2163 }
2164
2165 /* the peers are linked backwards first */
2166 curpeers->count++;
2167 newpeer->next = curpeers->remote;
2168 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002169 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002170 newpeer->conf.line = linenum;
2171
2172 newpeer->last_change = now.tv_sec;
2173 newpeer->id = strdup(args[1]);
2174
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002175 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002176 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002177 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002178 err_code |= ERR_ALERT | ERR_FATAL;
2179 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002180 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002181
2182 proto = protocol_by_family(sk->ss_family);
2183 if (!proto || !proto->connect) {
2184 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2185 file, linenum, args[0], args[1]);
2186 err_code |= ERR_ALERT | ERR_FATAL;
2187 goto out;
2188 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002189
2190 if (port1 != port2) {
2191 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2192 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002193 err_code |= ERR_ALERT | ERR_FATAL;
2194 goto out;
2195 }
2196
Willy Tarreau2aa38802013-02-20 19:20:59 +01002197 if (!port1) {
2198 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2199 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002200 err_code |= ERR_ALERT | ERR_FATAL;
2201 goto out;
2202 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002203
Emeric Brun32da3c42010-09-23 18:39:19 +02002204 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002205 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002206 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002207 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002208
Emeric Brun32da3c42010-09-23 18:39:19 +02002209 if (strcmp(newpeer->id, localpeer) == 0) {
2210 /* Current is local peer, it define a frontend */
2211 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002212 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002213
2214 if (!curpeers->peers_fe) {
2215 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2216 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2217 err_code |= ERR_ALERT | ERR_ABORT;
2218 goto out;
2219 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002220
Willy Tarreau237250c2011-07-29 01:49:03 +02002221 init_new_proxy(curpeers->peers_fe);
2222 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002223 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002224 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2225 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002226 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002227
2228 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2229
Willy Tarreau902636f2013-03-10 19:44:48 +01002230 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2231 if (errmsg && *errmsg) {
2232 indent_msg(&errmsg, 2);
2233 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002234 }
2235 else
2236 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2237 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002238 err_code |= ERR_FATAL;
2239 goto out;
2240 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002241
2242 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002243 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002244 l->maxconn = curpeers->peers_fe->maxconn;
2245 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002246 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002247 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002248 l->analysers |= curpeers->peers_fe->fe_req_ana;
2249 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002250 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2251 global.maxsock += l->maxconn;
2252 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002253 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002254 else {
2255 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2256 file, linenum, args[0], args[1],
2257 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2258 err_code |= ERR_FATAL;
2259 goto out;
2260 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002261 }
2262 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002263 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2264 curpeers->state = PR_STSTOPPED;
2265 }
2266 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2267 curpeers->state = PR_STNEW;
2268 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002269 else if (*args[0] != 0) {
2270 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2271 err_code |= ERR_ALERT | ERR_FATAL;
2272 goto out;
2273 }
2274
2275out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002276 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002277 return err_code;
2278}
2279
Baptiste Assmann325137d2015-04-13 23:40:55 +02002280/*
2281 * Parse a <resolvers> section.
2282 * Returns the error code, 0 if OK, or any combination of :
2283 * - ERR_ABORT: must abort ASAP
2284 * - ERR_FATAL: we can continue parsing but not start the service
2285 * - ERR_WARN: a warning has been emitted
2286 * - ERR_ALERT: an alert has been emitted
2287 * Only the two first ones can stop processing, the two others are just
2288 * indicators.
2289 */
2290int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2291{
2292 static struct dns_resolvers *curr_resolvers = NULL;
2293 struct dns_nameserver *newnameserver = NULL;
2294 const char *err;
2295 int err_code = 0;
2296 char *errmsg = NULL;
2297
2298 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2299 if (!*args[1]) {
2300 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2301 err_code |= ERR_ALERT | ERR_ABORT;
2302 goto out;
2303 }
2304
2305 err = invalid_char(args[1]);
2306 if (err) {
2307 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2308 file, linenum, *err, args[0], args[1]);
2309 err_code |= ERR_ALERT | ERR_ABORT;
2310 goto out;
2311 }
2312
2313 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2314 /* Error if two resolvers owns the same name */
2315 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2316 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2317 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2318 err_code |= ERR_ALERT | ERR_ABORT;
2319 }
2320 }
2321
Vincent Bernat02779b62016-04-03 13:48:43 +02002322 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002323 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2324 err_code |= ERR_ALERT | ERR_ABORT;
2325 goto out;
2326 }
2327
2328 /* default values */
2329 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2330 curr_resolvers->conf.file = strdup(file);
2331 curr_resolvers->conf.line = linenum;
2332 curr_resolvers->id = strdup(args[1]);
2333 curr_resolvers->query_ids = EB_ROOT;
2334 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002335 curr_resolvers->hold.valid = 10000;
2336 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002337 curr_resolvers->resolve_retries = 3;
2338 LIST_INIT(&curr_resolvers->nameserver_list);
2339 LIST_INIT(&curr_resolvers->curr_resolution);
2340 }
2341 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2342 struct sockaddr_storage *sk;
2343 int port1, port2;
2344 struct protocol *proto;
2345
2346 if (!*args[2]) {
2347 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2348 file, linenum, args[0]);
2349 err_code |= ERR_ALERT | ERR_FATAL;
2350 goto out;
2351 }
2352
2353 err = invalid_char(args[1]);
2354 if (err) {
2355 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2356 file, linenum, *err, args[1]);
2357 err_code |= ERR_ALERT | ERR_FATAL;
2358 goto out;
2359 }
2360
Baptiste Assmanna315c552015-11-02 22:55:49 +01002361 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2362 /* Error if two resolvers owns the same name */
2363 if (strcmp(newnameserver->id, args[1]) == 0) {
2364 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2365 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2366 err_code |= ERR_ALERT | ERR_FATAL;
2367 }
2368 }
2369
Vincent Bernat02779b62016-04-03 13:48:43 +02002370 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002371 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2372 err_code |= ERR_ALERT | ERR_ABORT;
2373 goto out;
2374 }
2375
2376 /* the nameservers are linked backward first */
2377 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2378 curr_resolvers->count_nameservers++;
2379 newnameserver->resolvers = curr_resolvers;
2380 newnameserver->conf.file = strdup(file);
2381 newnameserver->conf.line = linenum;
2382 newnameserver->id = strdup(args[1]);
2383
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002384 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002385 if (!sk) {
2386 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2387 err_code |= ERR_ALERT | ERR_FATAL;
2388 goto out;
2389 }
2390
2391 proto = protocol_by_family(sk->ss_family);
2392 if (!proto || !proto->connect) {
2393 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2394 file, linenum, args[0], args[1]);
2395 err_code |= ERR_ALERT | ERR_FATAL;
2396 goto out;
2397 }
2398
2399 if (port1 != port2) {
2400 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2401 file, linenum, args[0], args[1], args[2]);
2402 err_code |= ERR_ALERT | ERR_FATAL;
2403 goto out;
2404 }
2405
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002406 if (!port1 && !port2) {
2407 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2408 file, linenum, args[0], args[1]);
2409 err_code |= ERR_ALERT | ERR_FATAL;
2410 goto out;
2411 }
2412
Baptiste Assmann325137d2015-04-13 23:40:55 +02002413 newnameserver->addr = *sk;
2414 }
2415 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2416 const char *res;
2417 unsigned int time;
2418
2419 if (!*args[2]) {
2420 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2421 file, linenum, args[0]);
2422 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2423 err_code |= ERR_ALERT | ERR_FATAL;
2424 goto out;
2425 }
2426 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2427 if (res) {
2428 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2429 file, linenum, *res, args[0]);
2430 err_code |= ERR_ALERT | ERR_FATAL;
2431 goto out;
2432 }
2433 if (strcmp(args[1], "valid") == 0)
2434 curr_resolvers->hold.valid = time;
2435 else {
2436 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects 'valid'\n",
2437 file, linenum, args[0], args[1]);
2438 err_code |= ERR_ALERT | ERR_FATAL;
2439 goto out;
2440 }
2441
2442 }
2443 else if (strcmp(args[0], "resolve_retries") == 0) {
2444 if (!*args[1]) {
2445 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2446 file, linenum, args[0]);
2447 err_code |= ERR_ALERT | ERR_FATAL;
2448 goto out;
2449 }
2450 curr_resolvers->resolve_retries = atoi(args[1]);
2451 }
2452 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002453 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002454 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2455 file, linenum, args[0]);
2456 err_code |= ERR_ALERT | ERR_FATAL;
2457 goto out;
2458 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002459 else if (strcmp(args[1], "retry") == 0) {
2460 const char *res;
2461 unsigned int timeout_retry;
2462
2463 if (!*args[2]) {
2464 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2465 file, linenum, args[0], args[1]);
2466 err_code |= ERR_ALERT | ERR_FATAL;
2467 goto out;
2468 }
2469 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2470 if (res) {
2471 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2472 file, linenum, *res, args[0], args[1]);
2473 err_code |= ERR_ALERT | ERR_FATAL;
2474 goto out;
2475 }
2476 curr_resolvers->timeout.retry = timeout_retry;
2477 }
2478 else {
2479 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2480 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002481 err_code |= ERR_ALERT | ERR_FATAL;
2482 goto out;
2483 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002484 } /* neither "nameserver" nor "resolvers" */
2485 else if (*args[0] != 0) {
2486 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2487 err_code |= ERR_ALERT | ERR_FATAL;
2488 goto out;
2489 }
2490
2491 out:
2492 free(errmsg);
2493 return err_code;
2494}
Simon Horman0d16a402015-01-30 11:22:58 +09002495
2496/*
William Lallemand51097192015-04-14 16:35:22 +02002497 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002498 * Returns the error code, 0 if OK, or any combination of :
2499 * - ERR_ABORT: must abort ASAP
2500 * - ERR_FATAL: we can continue parsing but not start the service
2501 * - ERR_WARN: a warning has been emitted
2502 * - ERR_ALERT: an alert has been emitted
2503 * Only the two first ones can stop processing, the two others are just
2504 * indicators.
2505 */
2506int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2507{
2508 static struct mailers *curmailers = NULL;
2509 struct mailer *newmailer = NULL;
2510 const char *err;
2511 int err_code = 0;
2512 char *errmsg = NULL;
2513
2514 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2515 if (!*args[1]) {
2516 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2517 err_code |= ERR_ALERT | ERR_ABORT;
2518 goto out;
2519 }
2520
2521 err = invalid_char(args[1]);
2522 if (err) {
2523 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2524 file, linenum, *err, args[0], args[1]);
2525 err_code |= ERR_ALERT | ERR_ABORT;
2526 goto out;
2527 }
2528
2529 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2530 /*
2531 * If there are two proxies with the same name only following
2532 * combinations are allowed:
2533 */
2534 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002535 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 +09002536 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002537 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002538 }
2539 }
2540
Vincent Bernat02779b62016-04-03 13:48:43 +02002541 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002542 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2543 err_code |= ERR_ALERT | ERR_ABORT;
2544 goto out;
2545 }
2546
2547 curmailers->next = mailers;
2548 mailers = curmailers;
2549 curmailers->conf.file = strdup(file);
2550 curmailers->conf.line = linenum;
2551 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002552 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2553 * But need enough time so that timeouts don't occur
2554 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002555 }
2556 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2557 struct sockaddr_storage *sk;
2558 int port1, port2;
2559 struct protocol *proto;
2560
2561 if (!*args[2]) {
2562 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2563 file, linenum, args[0]);
2564 err_code |= ERR_ALERT | ERR_FATAL;
2565 goto out;
2566 }
2567
2568 err = invalid_char(args[1]);
2569 if (err) {
2570 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2571 file, linenum, *err, args[1]);
2572 err_code |= ERR_ALERT | ERR_FATAL;
2573 goto out;
2574 }
2575
Vincent Bernat02779b62016-04-03 13:48:43 +02002576 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002577 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2578 err_code |= ERR_ALERT | ERR_ABORT;
2579 goto out;
2580 }
2581
2582 /* the mailers are linked backwards first */
2583 curmailers->count++;
2584 newmailer->next = curmailers->mailer_list;
2585 curmailers->mailer_list = newmailer;
2586 newmailer->mailers = curmailers;
2587 newmailer->conf.file = strdup(file);
2588 newmailer->conf.line = linenum;
2589
2590 newmailer->id = strdup(args[1]);
2591
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002592 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002593 if (!sk) {
2594 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2595 err_code |= ERR_ALERT | ERR_FATAL;
2596 goto out;
2597 }
2598
2599 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002600 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2601 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002602 file, linenum, args[0], args[1]);
2603 err_code |= ERR_ALERT | ERR_FATAL;
2604 goto out;
2605 }
2606
2607 if (port1 != port2) {
2608 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2609 file, linenum, args[0], args[1], args[2]);
2610 err_code |= ERR_ALERT | ERR_FATAL;
2611 goto out;
2612 }
2613
2614 if (!port1) {
2615 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2616 file, linenum, args[0], args[1], args[2]);
2617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
2619 }
2620
2621 newmailer->addr = *sk;
2622 newmailer->proto = proto;
2623 newmailer->xprt = &raw_sock;
2624 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002625 }
2626 else if (strcmp(args[0], "timeout") == 0) {
2627 if (!*args[1]) {
2628 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2629 file, linenum, args[0]);
2630 err_code |= ERR_ALERT | ERR_FATAL;
2631 goto out;
2632 }
2633 else if (strcmp(args[1], "mail") == 0) {
2634 const char *res;
2635 unsigned int timeout_mail;
2636 if (!*args[2]) {
2637 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2638 file, linenum, args[0], args[1]);
2639 err_code |= ERR_ALERT | ERR_FATAL;
2640 goto out;
2641 }
2642 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2643 if (res) {
2644 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2645 file, linenum, *res, args[0]);
2646 err_code |= ERR_ALERT | ERR_FATAL;
2647 goto out;
2648 }
2649 if (timeout_mail <= 0) {
2650 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2651 err_code |= ERR_ALERT | ERR_FATAL;
2652 goto out;
2653 }
2654 curmailers->timeout.mail = timeout_mail;
2655 } else {
2656 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2657 file, linenum, args[0], args[1]);
2658 err_code |= ERR_ALERT | ERR_FATAL;
2659 goto out;
2660 }
2661 }
Simon Horman0d16a402015-01-30 11:22:58 +09002662 else if (*args[0] != 0) {
2663 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2664 err_code |= ERR_ALERT | ERR_FATAL;
2665 goto out;
2666 }
2667
2668out:
2669 free(errmsg);
2670 return err_code;
2671}
2672
Simon Horman9dc49962015-01-30 11:22:59 +09002673static void free_email_alert(struct proxy *p)
2674{
2675 free(p->email_alert.mailers.name);
2676 p->email_alert.mailers.name = NULL;
2677 free(p->email_alert.from);
2678 p->email_alert.from = NULL;
2679 free(p->email_alert.to);
2680 p->email_alert.to = NULL;
2681 free(p->email_alert.myhostname);
2682 p->email_alert.myhostname = NULL;
2683}
2684
Willy Tarreau3842f002009-06-14 11:39:52 +02002685int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002686{
2687 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002688 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002689 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002690 int rc;
2691 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002692 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002693 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002694 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002695 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002696 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002697
Willy Tarreau977b8e42006-12-29 14:19:17 +01002698 if (!strcmp(args[0], "listen"))
2699 rc = PR_CAP_LISTEN;
2700 else if (!strcmp(args[0], "frontend"))
2701 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002702 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002703 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002704 else
2705 rc = PR_CAP_NONE;
2706
2707 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002708 if (!*args[1]) {
2709 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
2710 " optionnally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
2711 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002712 err_code |= ERR_ALERT | ERR_ABORT;
2713 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002714 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002715
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002716 err = invalid_char(args[1]);
2717 if (err) {
2718 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2719 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002720 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002721 }
2722
Willy Tarreau8f50b682015-05-26 11:45:02 +02002723 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2724 if (curproxy) {
2725 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2726 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2727 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002728 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002729 }
2730
Vincent Bernat02779b62016-04-03 13:48:43 +02002731 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002732 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002733 err_code |= ERR_ALERT | ERR_ABORT;
2734 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002735 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002736
Willy Tarreau97cb7802010-01-03 20:23:58 +01002737 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002738 curproxy->next = proxy;
2739 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002740 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2741 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002742 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002743 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002744 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002745 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002746
William Lallemand6e62fb62015-04-28 16:55:23 +02002747 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2748 if (curproxy->cap & PR_CAP_FE)
2749 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2750 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002751 }
2752
2753 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002754 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002755 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002756
Willy Tarreaubaaee002006-06-26 02:48:02 +02002757 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002758 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002759 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002760 curproxy->no_options = defproxy.no_options;
2761 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002762 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002763 curproxy->except_net = defproxy.except_net;
2764 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002765 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002766 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002767
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002768 if (defproxy.fwdfor_hdr_len) {
2769 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2770 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2771 }
2772
Willy Tarreaub86db342009-11-30 11:50:16 +01002773 if (defproxy.orgto_hdr_len) {
2774 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2775 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2776 }
2777
Mark Lamourinec2247f02012-01-04 13:02:01 -05002778 if (defproxy.server_id_hdr_len) {
2779 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2780 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2781 }
2782
Willy Tarreau977b8e42006-12-29 14:19:17 +01002783 if (curproxy->cap & PR_CAP_FE) {
2784 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002785 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002786 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002787
2788 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002789 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2790 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002791
2792 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2793 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002794
Willy Tarreau977b8e42006-12-29 14:19:17 +01002795 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002796 curproxy->lbprm.algo = defproxy.lbprm.algo;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002797 curproxy->fullconn = defproxy.fullconn;
2798 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002799 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002800 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002801
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002802 if (defproxy.check_req) {
2803 curproxy->check_req = calloc(1, defproxy.check_len);
2804 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2805 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002806 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002807
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002808 if (defproxy.expect_str) {
2809 curproxy->expect_str = strdup(defproxy.expect_str);
2810 if (defproxy.expect_regex) {
2811 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002812 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2813 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002814 }
2815 }
2816
Willy Tarreau67402132012-05-31 20:40:20 +02002817 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002818 if (defproxy.cookie_name)
2819 curproxy->cookie_name = strdup(defproxy.cookie_name);
2820 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002821 if (defproxy.cookie_domain)
2822 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002823
Willy Tarreau31936852010-10-06 16:59:56 +02002824 if (defproxy.cookie_maxidle)
2825 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2826
2827 if (defproxy.cookie_maxlife)
2828 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2829
Emeric Brun647caf12009-06-30 17:57:00 +02002830 if (defproxy.rdp_cookie_name)
2831 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2832 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2833
Willy Tarreau01732802007-11-01 22:48:15 +01002834 if (defproxy.url_param_name)
2835 curproxy->url_param_name = strdup(defproxy.url_param_name);
2836 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002837
Benoitaffb4812009-03-25 13:02:10 +01002838 if (defproxy.hh_name)
2839 curproxy->hh_name = strdup(defproxy.hh_name);
2840 curproxy->hh_len = defproxy.hh_len;
2841 curproxy->hh_match_domain = defproxy.hh_match_domain;
2842
Willy Tarreauef9a3602012-12-08 22:29:20 +01002843 if (defproxy.conn_src.iface_name)
2844 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2845 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002846 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002847#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002848 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002849#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002850 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002851 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002852
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002853 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002854 if (defproxy.capture_name)
2855 curproxy->capture_name = strdup(defproxy.capture_name);
2856 curproxy->capture_namelen = defproxy.capture_namelen;
2857 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002858 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002859
Willy Tarreau977b8e42006-12-29 14:19:17 +01002860 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002861 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002862 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002863 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002864 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002865 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002866 curproxy->mon_net = defproxy.mon_net;
2867 curproxy->mon_mask = defproxy.mon_mask;
2868 if (defproxy.monitor_uri)
2869 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2870 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002871 if (defproxy.defbe.name)
2872 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002873
2874 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002875 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2876 if (curproxy->conf.logformat_string &&
2877 curproxy->conf.logformat_string != default_http_log_format &&
2878 curproxy->conf.logformat_string != default_tcp_log_format &&
2879 curproxy->conf.logformat_string != clf_http_log_format)
2880 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2881
2882 if (defproxy.conf.lfs_file) {
2883 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2884 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2885 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002886
2887 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2888 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2889 if (curproxy->conf.logformat_sd_string &&
2890 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2891 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2892
2893 if (defproxy.conf.lfsd_file) {
2894 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2895 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2896 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 }
2898
2899 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002900 curproxy->timeout.connect = defproxy.timeout.connect;
2901 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002902 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002903 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002904 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002905 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002906 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002907 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002908 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002909 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002910 }
2911
Willy Tarreaubaaee002006-06-26 02:48:02 +02002912 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002913 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002914
2915 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002916 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002917 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002918 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002919 LIST_INIT(&node->list);
2920 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2921 }
2922
Willy Tarreau62a61232013-04-12 18:13:46 +02002923 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2924 if (curproxy->conf.uniqueid_format_string)
2925 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2926
Dragan Dosen43885c72015-10-01 13:18:13 +02002927 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002928
Willy Tarreau62a61232013-04-12 18:13:46 +02002929 if (defproxy.conf.uif_file) {
2930 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2931 curproxy->conf.uif_line = defproxy.conf.uif_line;
2932 }
William Lallemanda73203e2012-03-12 12:48:57 +01002933
2934 /* copy default header unique id */
2935 if (defproxy.header_unique_id)
2936 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2937
William Lallemand82fe75c2012-10-23 10:25:10 +02002938 /* default compression options */
2939 if (defproxy.comp != NULL) {
2940 curproxy->comp = calloc(1, sizeof(struct comp));
2941 curproxy->comp->algos = defproxy.comp->algos;
2942 curproxy->comp->types = defproxy.comp->types;
2943 }
2944
Willy Tarreaubaaee002006-06-26 02:48:02 +02002945 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002946 curproxy->conf.used_listener_id = EB_ROOT;
2947 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002948
Simon Horman98637e52014-06-20 12:30:16 +09002949 if (defproxy.check_path)
2950 curproxy->check_path = strdup(defproxy.check_path);
2951 if (defproxy.check_command)
2952 curproxy->check_command = strdup(defproxy.check_command);
2953
Simon Horman9dc49962015-01-30 11:22:59 +09002954 if (defproxy.email_alert.mailers.name)
2955 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
2956 if (defproxy.email_alert.from)
2957 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
2958 if (defproxy.email_alert.to)
2959 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
2960 if (defproxy.email_alert.myhostname)
2961 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09002962 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01002963 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09002964
Willy Tarreau93893792009-07-23 13:19:11 +02002965 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002966 }
2967 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
2968 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002969 /* FIXME-20070101: we should do this too at the end of the
2970 * config parsing to free all default values.
2971 */
William Lallemand6e62fb62015-04-28 16:55:23 +02002972 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2973 err_code |= ERR_ABORT;
2974 goto out;
2975 }
2976
Willy Tarreaua534fea2008-08-03 12:19:50 +02002977 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09002978 free(defproxy.check_command);
2979 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002980 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02002981 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002982 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002983 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01002984 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02002985 free(defproxy.capture_name);
2986 free(defproxy.monitor_uri);
2987 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01002988 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002989 free(defproxy.fwdfor_hdr_name);
2990 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01002991 free(defproxy.orgto_hdr_name);
2992 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05002993 free(defproxy.server_id_hdr_name);
2994 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002995 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002996 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002997 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02002998 free(defproxy.expect_regex);
2999 defproxy.expect_regex = NULL;
3000 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003001
Willy Tarreau62a61232013-04-12 18:13:46 +02003002 if (defproxy.conf.logformat_string != default_http_log_format &&
3003 defproxy.conf.logformat_string != default_tcp_log_format &&
3004 defproxy.conf.logformat_string != clf_http_log_format)
3005 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003006
Willy Tarreau62a61232013-04-12 18:13:46 +02003007 free(defproxy.conf.uniqueid_format_string);
3008 free(defproxy.conf.lfs_file);
3009 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003010 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003011 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003012
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003013 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3014 free(defproxy.conf.logformat_sd_string);
3015 free(defproxy.conf.lfsd_file);
3016
Willy Tarreaua534fea2008-08-03 12:19:50 +02003017 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003018 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003019
Willy Tarreaubaaee002006-06-26 02:48:02 +02003020 /* we cannot free uri_auth because it might already be used */
3021 init_default_instance();
3022 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003023 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3024 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003025 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003026 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003027 }
3028 else if (curproxy == NULL) {
3029 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003030 err_code |= ERR_ALERT | ERR_FATAL;
3031 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003032 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003033
3034 /* update the current file and line being parsed */
3035 curproxy->conf.args.file = curproxy->conf.file;
3036 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003037
3038 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003039 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3040 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3041 if (err_code & ERR_FATAL)
3042 goto out;
3043 }
3044 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003045 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003046 int cur_arg;
3047
Willy Tarreaubaaee002006-06-26 02:48:02 +02003048 if (curproxy == &defproxy) {
3049 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003050 err_code |= ERR_ALERT | ERR_FATAL;
3051 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003052 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003053 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003054 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003055
Willy Tarreau24709282013-03-10 21:32:12 +01003056 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003057 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003058 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003059 err_code |= ERR_ALERT | ERR_FATAL;
3060 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003061 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003062
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003063 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003064
3065 /* use default settings for unix sockets */
3066 bind_conf->ux.uid = global.unix_bind.ux.uid;
3067 bind_conf->ux.gid = global.unix_bind.ux.gid;
3068 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003069
3070 /* NOTE: the following line might create several listeners if there
3071 * are comma-separated IPs or port ranges. So all further processing
3072 * will have to be applied to all listeners created after last_listen.
3073 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003074 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3075 if (errmsg && *errmsg) {
3076 indent_msg(&errmsg, 2);
3077 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003078 }
3079 else
3080 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3081 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003082 err_code |= ERR_ALERT | ERR_FATAL;
3083 goto out;
3084 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003085
Willy Tarreau4348fad2012-09-20 16:48:07 +02003086 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3087 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003088 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003089 }
3090
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003091 cur_arg = 2;
3092 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003093 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003094 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003095 char *err;
3096
Willy Tarreau26982662012-09-12 23:17:10 +02003097 kw = bind_find_kw(args[cur_arg]);
3098 if (kw) {
3099 char *err = NULL;
3100 int code;
3101
3102 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003103 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3104 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003105 cur_arg += 1 + kw->skip ;
3106 err_code |= ERR_ALERT | ERR_FATAL;
3107 goto out;
3108 }
3109
Willy Tarreau4348fad2012-09-20 16:48:07 +02003110 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003111 err_code |= code;
3112
3113 if (code) {
3114 if (err && *err) {
3115 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003116 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003117 }
3118 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003119 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3120 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003121 if (code & ERR_FATAL) {
3122 free(err);
3123 cur_arg += 1 + kw->skip;
3124 goto out;
3125 }
3126 }
3127 free(err);
3128 cur_arg += 1 + kw->skip;
3129 continue;
3130 }
3131
Willy Tarreau8638f482012-09-18 18:01:17 +02003132 err = NULL;
3133 if (!bind_dumped) {
3134 bind_dump_kws(&err);
3135 indent_msg(&err, 4);
3136 bind_dumped = 1;
3137 }
3138
3139 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3140 file, linenum, args[0], args[1], args[cur_arg],
3141 err ? " Registered keywords :" : "", err ? err : "");
3142 free(err);
3143
Willy Tarreau93893792009-07-23 13:19:11 +02003144 err_code |= ERR_ALERT | ERR_FATAL;
3145 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003146 }
Willy Tarreau93893792009-07-23 13:19:11 +02003147 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003148 }
3149 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003150 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003151 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3152 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003153 err_code |= ERR_ALERT | ERR_FATAL;
3154 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003155 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003156 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003157 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003158
Willy Tarreaubaaee002006-06-26 02:48:02 +02003159 /* flush useless bits */
3160 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003162 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003163 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003164 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003165 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003166
William Lallemanddf1425a2015-04-28 20:17:49 +02003167 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3168 goto out;
3169
Willy Tarreau1c47f852006-07-09 08:22:27 +02003170 if (!*args[1]) {
3171 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3172 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003173 err_code |= ERR_ALERT | ERR_FATAL;
3174 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003175 }
3176
Willy Tarreaua534fea2008-08-03 12:19:50 +02003177 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003178 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003179 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003180 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003181 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3182
Willy Tarreau93893792009-07-23 13:19:11 +02003183 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003184 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003185 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003186 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3187 goto out;
3188
Willy Tarreaubaaee002006-06-26 02:48:02 +02003189 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3190 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3191 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3192 else {
3193 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003194 err_code |= ERR_ALERT | ERR_FATAL;
3195 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003196 }
3197 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003198 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003199 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003200
3201 if (curproxy == &defproxy) {
3202 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3203 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003204 err_code |= ERR_ALERT | ERR_FATAL;
3205 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003206 }
3207
William Lallemanddf1425a2015-04-28 20:17:49 +02003208 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3209 goto out;
3210
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003211 if (!*args[1]) {
3212 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3213 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003214 err_code |= ERR_ALERT | ERR_FATAL;
3215 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003216 }
3217
3218 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003219 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003220 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003221
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003222 if (curproxy->uuid <= 0) {
3223 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003224 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003225 err_code |= ERR_ALERT | ERR_FATAL;
3226 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003227 }
3228
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003229 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3230 if (node) {
3231 struct proxy *target = container_of(node, struct proxy, conf.id);
3232 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3233 file, linenum, proxy_type_str(curproxy), curproxy->id,
3234 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3235 err_code |= ERR_ALERT | ERR_FATAL;
3236 goto out;
3237 }
3238 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003239 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003240 else if (!strcmp(args[0], "description")) {
3241 int i, len=0;
3242 char *d;
3243
Cyril Bonté99ed3272010-01-24 23:29:44 +01003244 if (curproxy == &defproxy) {
3245 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3246 file, linenum, args[0]);
3247 err_code |= ERR_ALERT | ERR_FATAL;
3248 goto out;
3249 }
3250
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003251 if (!*args[1]) {
3252 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3253 file, linenum, args[0]);
3254 return -1;
3255 }
3256
Willy Tarreau348acfe2014-04-14 15:00:39 +02003257 for (i = 1; *args[i]; i++)
3258 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003259
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003260 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003261 curproxy->desc = d;
3262
Willy Tarreau348acfe2014-04-14 15:00:39 +02003263 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3264 for (i = 2; *args[i]; i++)
3265 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003266
3267 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003268 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003269 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3270 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003271 curproxy->state = PR_STSTOPPED;
3272 }
3273 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003274 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3275 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003276 curproxy->state = PR_STNEW;
3277 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003278 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3279 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003280 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003281
3282 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003283 unsigned int low, high;
3284
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003285 if (strcmp(args[cur_arg], "all") == 0) {
3286 set = 0;
3287 break;
3288 }
3289 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003290 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003291 }
3292 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003293 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003294 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003295 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003296 char *dash = strchr(args[cur_arg], '-');
3297
3298 low = high = str2uic(args[cur_arg]);
3299 if (dash)
3300 high = str2uic(dash + 1);
3301
3302 if (high < low) {
3303 unsigned int swap = low;
3304 low = high;
3305 high = swap;
3306 }
3307
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003308 if (low < 1 || high > LONGBITS) {
3309 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3310 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003311 err_code |= ERR_ALERT | ERR_FATAL;
3312 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003313 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003314 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003315 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003316 }
3317 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003318 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3319 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003320 err_code |= ERR_ALERT | ERR_FATAL;
3321 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003322 }
3323 cur_arg++;
3324 }
3325 curproxy->bind_proc = set;
3326 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003327 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003328 if (curproxy == &defproxy) {
3329 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003330 err_code |= ERR_ALERT | ERR_FATAL;
3331 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003332 }
3333
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003334 err = invalid_char(args[1]);
3335 if (err) {
3336 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3337 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003338 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003339 }
3340
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003341 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003342 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3343 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003344 err_code |= ERR_ALERT | ERR_FATAL;
3345 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003346 }
3347 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003348 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3349 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003350
Willy Tarreau977b8e42006-12-29 14:19:17 +01003351 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003352 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003353
Willy Tarreaubaaee002006-06-26 02:48:02 +02003354 if (*(args[1]) == 0) {
3355 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3356 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003359 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003360
Willy Tarreau67402132012-05-31 20:40:20 +02003361 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003362 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003363 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003364 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003365 curproxy->cookie_name = strdup(args[1]);
3366 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003367
Willy Tarreaubaaee002006-06-26 02:48:02 +02003368 cur_arg = 2;
3369 while (*(args[cur_arg])) {
3370 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003371 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003372 }
3373 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003374 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003375 }
3376 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003377 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003378 }
3379 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003380 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003381 }
3382 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003383 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003384 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003385 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003386 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003387 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003388 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003389 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003390 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003391 else if (!strcmp(args[cur_arg], "httponly")) {
3392 curproxy->ck_opts |= PR_CK_HTTPONLY;
3393 }
3394 else if (!strcmp(args[cur_arg], "secure")) {
3395 curproxy->ck_opts |= PR_CK_SECURE;
3396 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003397 else if (!strcmp(args[cur_arg], "domain")) {
3398 if (!*args[cur_arg + 1]) {
3399 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3400 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003401 err_code |= ERR_ALERT | ERR_FATAL;
3402 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003403 }
3404
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003405 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003406 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003407 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3408 " dots nor does not start with a dot."
3409 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003410 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003411 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003412 }
3413
3414 err = invalid_domainchar(args[cur_arg + 1]);
3415 if (err) {
3416 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3417 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003418 err_code |= ERR_ALERT | ERR_FATAL;
3419 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003420 }
3421
Willy Tarreau68a897b2009-12-03 23:28:34 +01003422 if (!curproxy->cookie_domain) {
3423 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3424 } else {
3425 /* one domain was already specified, add another one by
3426 * building the string which will be returned along with
3427 * the cookie.
3428 */
3429 char *new_ptr;
3430 int new_len = strlen(curproxy->cookie_domain) +
3431 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3432 new_ptr = malloc(new_len);
3433 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3434 free(curproxy->cookie_domain);
3435 curproxy->cookie_domain = new_ptr;
3436 }
Willy Tarreau31936852010-10-06 16:59:56 +02003437 cur_arg++;
3438 }
3439 else if (!strcmp(args[cur_arg], "maxidle")) {
3440 unsigned int maxidle;
3441 const char *res;
3442
3443 if (!*args[cur_arg + 1]) {
3444 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3445 file, linenum, args[cur_arg]);
3446 err_code |= ERR_ALERT | ERR_FATAL;
3447 goto out;
3448 }
3449
3450 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3451 if (res) {
3452 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3453 file, linenum, *res, args[cur_arg]);
3454 err_code |= ERR_ALERT | ERR_FATAL;
3455 goto out;
3456 }
3457 curproxy->cookie_maxidle = maxidle;
3458 cur_arg++;
3459 }
3460 else if (!strcmp(args[cur_arg], "maxlife")) {
3461 unsigned int maxlife;
3462 const char *res;
3463
3464 if (!*args[cur_arg + 1]) {
3465 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3466 file, linenum, args[cur_arg]);
3467 err_code |= ERR_ALERT | ERR_FATAL;
3468 goto out;
3469 }
3470
3471 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3472 if (res) {
3473 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3474 file, linenum, *res, args[cur_arg]);
3475 err_code |= ERR_ALERT | ERR_FATAL;
3476 goto out;
3477 }
3478 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003479 cur_arg++;
3480 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003481 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003482 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 +02003483 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003484 err_code |= ERR_ALERT | ERR_FATAL;
3485 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003486 }
3487 cur_arg++;
3488 }
Willy Tarreau67402132012-05-31 20:40:20 +02003489 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003490 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3491 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003492 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003493 }
3494
Willy Tarreau67402132012-05-31 20:40:20 +02003495 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003496 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3497 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003498 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003499 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003500
Willy Tarreau67402132012-05-31 20:40:20 +02003501 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003502 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3503 file, linenum);
3504 err_code |= ERR_ALERT | ERR_FATAL;
3505 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003506 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003507 else if (!strcmp(args[0], "email-alert")) {
3508 if (*(args[1]) == 0) {
3509 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3510 file, linenum, args[0]);
3511 err_code |= ERR_ALERT | ERR_FATAL;
3512 goto out;
3513 }
3514
3515 if (!strcmp(args[1], "from")) {
3516 if (*(args[1]) == 0) {
3517 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3518 file, linenum, args[1]);
3519 err_code |= ERR_ALERT | ERR_FATAL;
3520 goto out;
3521 }
3522 free(curproxy->email_alert.from);
3523 curproxy->email_alert.from = strdup(args[2]);
3524 }
3525 else if (!strcmp(args[1], "mailers")) {
3526 if (*(args[1]) == 0) {
3527 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3528 file, linenum, args[1]);
3529 err_code |= ERR_ALERT | ERR_FATAL;
3530 goto out;
3531 }
3532 free(curproxy->email_alert.mailers.name);
3533 curproxy->email_alert.mailers.name = strdup(args[2]);
3534 }
3535 else if (!strcmp(args[1], "myhostname")) {
3536 if (*(args[1]) == 0) {
3537 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3538 file, linenum, args[1]);
3539 err_code |= ERR_ALERT | ERR_FATAL;
3540 goto out;
3541 }
3542 free(curproxy->email_alert.myhostname);
3543 curproxy->email_alert.myhostname = strdup(args[2]);
3544 }
Simon Horman64e34162015-02-06 11:11:57 +09003545 else if (!strcmp(args[1], "level")) {
3546 curproxy->email_alert.level = get_log_level(args[2]);
3547 if (curproxy->email_alert.level < 0) {
3548 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3549 file, linenum, args[1], args[2]);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 goto out;
3552 }
3553 }
Simon Horman9dc49962015-01-30 11:22:59 +09003554 else if (!strcmp(args[1], "to")) {
3555 if (*(args[1]) == 0) {
3556 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3557 file, linenum, args[1]);
3558 err_code |= ERR_ALERT | ERR_FATAL;
3559 goto out;
3560 }
3561 free(curproxy->email_alert.to);
3562 curproxy->email_alert.to = strdup(args[2]);
3563 }
3564 else {
3565 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3566 file, linenum, args[1]);
3567 err_code |= ERR_ALERT | ERR_FATAL;
3568 goto out;
3569 }
Simon Horman64e34162015-02-06 11:11:57 +09003570 /* Indicate that the email_alert is at least partially configured */
3571 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003572 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003573 else if (!strcmp(args[0], "external-check")) {
3574 if (*(args[1]) == 0) {
3575 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3576 file, linenum, args[0]);
3577 err_code |= ERR_ALERT | ERR_FATAL;
3578 goto out;
3579 }
3580
3581 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003582 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003583 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003584 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003585 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3586 file, linenum, args[1]);
3587 err_code |= ERR_ALERT | ERR_FATAL;
3588 goto out;
3589 }
3590 free(curproxy->check_command);
3591 curproxy->check_command = strdup(args[2]);
3592 }
3593 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003594 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003595 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003596 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003597 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3598 file, linenum, args[1]);
3599 err_code |= ERR_ALERT | ERR_FATAL;
3600 goto out;
3601 }
3602 free(curproxy->check_path);
3603 curproxy->check_path = strdup(args[2]);
3604 }
3605 else {
3606 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3607 file, linenum, args[1]);
3608 err_code |= ERR_ALERT | ERR_FATAL;
3609 goto out;
3610 }
3611 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003612 else if (!strcmp(args[0], "persist")) { /* persist */
3613 if (*(args[1]) == 0) {
3614 Alert("parsing [%s:%d] : missing persist method.\n",
3615 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003616 err_code |= ERR_ALERT | ERR_FATAL;
3617 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003618 }
3619
3620 if (!strncmp(args[1], "rdp-cookie", 10)) {
3621 curproxy->options2 |= PR_O2_RDPC_PRST;
3622
Emeric Brunb982a3d2010-01-04 15:45:53 +01003623 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003624 const char *beg, *end;
3625
3626 beg = args[1] + 11;
3627 end = strchr(beg, ')');
3628
William Lallemanddf1425a2015-04-28 20:17:49 +02003629 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3630 goto out;
3631
Emeric Brun647caf12009-06-30 17:57:00 +02003632 if (!end || end == beg) {
3633 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3634 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003635 err_code |= ERR_ALERT | ERR_FATAL;
3636 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003637 }
3638
3639 free(curproxy->rdp_cookie_name);
3640 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3641 curproxy->rdp_cookie_len = end-beg;
3642 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003643 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003644 free(curproxy->rdp_cookie_name);
3645 curproxy->rdp_cookie_name = strdup("msts");
3646 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3647 }
3648 else { /* syntax */
3649 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3650 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003651 err_code |= ERR_ALERT | ERR_FATAL;
3652 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003653 }
3654 }
3655 else {
3656 Alert("parsing [%s:%d] : unknown persist method.\n",
3657 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003658 err_code |= ERR_ALERT | ERR_FATAL;
3659 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003660 }
3661 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003662 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003663 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3664 err_code |= ERR_ALERT | ERR_FATAL;
3665 goto out;
3666 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003667 else if (!strcmp(args[0], "load-server-state-from-file")) {
3668 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3669 err_code |= ERR_WARN;
3670 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3671 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3672 }
3673 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3674 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3675 }
3676 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3677 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3678 }
3679 else {
3680 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3681 file, linenum, args[0], args[1]);
3682 err_code |= ERR_ALERT | ERR_FATAL;
3683 goto out;
3684 }
3685 }
3686 else if (!strcmp(args[0], "server-state-file-name")) {
3687 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3688 err_code |= ERR_WARN;
3689 if (*(args[1]) == 0) {
3690 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3691 file, linenum, args[0]);
3692 err_code |= ERR_ALERT | ERR_FATAL;
3693 goto out;
3694 }
3695 else if (!strcmp(args[1], "use-backend-name"))
3696 curproxy->server_state_file_name = strdup(curproxy->id);
3697 else
3698 curproxy->server_state_file_name = strdup(args[1]);
3699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003700 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003701 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003702 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003703
Willy Tarreaubaaee002006-06-26 02:48:02 +02003704 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003705 if (curproxy == &defproxy) {
3706 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3707 err_code |= ERR_ALERT | ERR_FATAL;
3708 goto out;
3709 }
3710
William Lallemand1a748ae2015-05-19 16:37:23 +02003711 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3712 goto out;
3713
Willy Tarreaubaaee002006-06-26 02:48:02 +02003714 if (*(args[4]) == 0) {
3715 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3716 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003717 err_code |= ERR_ALERT | ERR_FATAL;
3718 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003719 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003720 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003721 curproxy->capture_name = strdup(args[2]);
3722 curproxy->capture_namelen = strlen(curproxy->capture_name);
3723 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003724 curproxy->to_log |= LW_COOKIE;
3725 }
3726 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3727 struct cap_hdr *hdr;
3728
3729 if (curproxy == &defproxy) {
3730 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 +02003731 err_code |= ERR_ALERT | ERR_FATAL;
3732 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003733 }
3734
William Lallemand1a748ae2015-05-19 16:37:23 +02003735 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3736 goto out;
3737
Willy Tarreaubaaee002006-06-26 02:48:02 +02003738 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3739 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3740 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003741 err_code |= ERR_ALERT | ERR_FATAL;
3742 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003743 }
3744
Vincent Bernat02779b62016-04-03 13:48:43 +02003745 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 hdr->next = curproxy->req_cap;
3747 hdr->name = strdup(args[3]);
3748 hdr->namelen = strlen(args[3]);
3749 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003750 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003751 hdr->index = curproxy->nb_req_cap++;
3752 curproxy->req_cap = hdr;
3753 curproxy->to_log |= LW_REQHDR;
3754 }
3755 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3756 struct cap_hdr *hdr;
3757
3758 if (curproxy == &defproxy) {
3759 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 +02003760 err_code |= ERR_ALERT | ERR_FATAL;
3761 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003762 }
3763
William Lallemand1a748ae2015-05-19 16:37:23 +02003764 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3765 goto out;
3766
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3768 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3769 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003770 err_code |= ERR_ALERT | ERR_FATAL;
3771 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003772 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003773 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003774 hdr->next = curproxy->rsp_cap;
3775 hdr->name = strdup(args[3]);
3776 hdr->namelen = strlen(args[3]);
3777 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003778 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 hdr->index = curproxy->nb_rsp_cap++;
3780 curproxy->rsp_cap = hdr;
3781 curproxy->to_log |= LW_RSPHDR;
3782 }
3783 else {
3784 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3785 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003786 err_code |= ERR_ALERT | ERR_FATAL;
3787 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003788 }
3789 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003790 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003791 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003792 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003793
William Lallemanddf1425a2015-04-28 20:17:49 +02003794 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3795 goto out;
3796
Willy Tarreaubaaee002006-06-26 02:48:02 +02003797 if (*(args[1]) == 0) {
3798 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3799 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003800 err_code |= ERR_ALERT | ERR_FATAL;
3801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003802 }
3803 curproxy->conn_retries = atol(args[1]);
3804 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003805 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003806 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003807
3808 if (curproxy == &defproxy) {
3809 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3810 err_code |= ERR_ALERT | ERR_FATAL;
3811 goto out;
3812 }
3813
Willy Tarreau20b0de52012-12-24 15:45:22 +01003814 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003815 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003816 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3817 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3818 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3819 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003820 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 +01003821 file, linenum, args[0]);
3822 err_code |= ERR_WARN;
3823 }
3824
Willy Tarreauff011f22011-01-06 17:51:27 +01003825 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003826
Willy Tarreauff011f22011-01-06 17:51:27 +01003827 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003828 err_code |= ERR_ALERT | ERR_ABORT;
3829 goto out;
3830 }
3831
Willy Tarreau5002f572014-04-23 01:32:02 +02003832 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003833 err_code |= warnif_cond_conflicts(rule->cond,
3834 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3835 file, linenum);
3836
Willy Tarreauff011f22011-01-06 17:51:27 +01003837 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003838 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003839 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003840 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003841
3842 if (curproxy == &defproxy) {
3843 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3844 err_code |= ERR_ALERT | ERR_FATAL;
3845 goto out;
3846 }
3847
3848 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003849 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003850 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3851 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003852 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3853 file, linenum, args[0]);
3854 err_code |= ERR_WARN;
3855 }
3856
3857 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3858
3859 if (!rule) {
3860 err_code |= ERR_ALERT | ERR_ABORT;
3861 goto out;
3862 }
3863
3864 err_code |= warnif_cond_conflicts(rule->cond,
3865 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3866 file, linenum);
3867
3868 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3869 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003870 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3871 /* set the header name and length into the proxy structure */
3872 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3873 err_code |= ERR_WARN;
3874
3875 if (!*args[1]) {
3876 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3877 file, linenum, args[0]);
3878 err_code |= ERR_ALERT | ERR_FATAL;
3879 goto out;
3880 }
3881
3882 /* set the desired header name */
3883 free(curproxy->server_id_hdr_name);
3884 curproxy->server_id_hdr_name = strdup(args[1]);
3885 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3886 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003887 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003888 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003889
Willy Tarreaub099aca2008-10-12 17:26:37 +02003890 if (curproxy == &defproxy) {
3891 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003892 err_code |= ERR_ALERT | ERR_FATAL;
3893 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003894 }
3895
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003896 /* emulate "block" using "http-request block". Since these rules are supposed to
3897 * be processed before all http-request rules, we put them into their own list
3898 * and will insert them at the end.
3899 */
3900 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3901 if (!rule) {
3902 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003903 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003904 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003905 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3906 err_code |= warnif_cond_conflicts(rule->cond,
3907 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3908 file, linenum);
3909 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003910
3911 if (!already_warned(WARN_BLOCK_DEPRECATED))
3912 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]);
3913
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003914 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003915 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003916 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003917
Cyril Bonté99ed3272010-01-24 23:29:44 +01003918 if (curproxy == &defproxy) {
3919 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3920 err_code |= ERR_ALERT | ERR_FATAL;
3921 goto out;
3922 }
3923
Willy Tarreaube4653b2015-05-28 15:26:58 +02003924 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003925 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3926 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003927 err_code |= ERR_ALERT | ERR_FATAL;
3928 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003929 }
3930
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003931 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003932 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003933 err_code |= warnif_cond_conflicts(rule->cond,
3934 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3935 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003936 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003937 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003938 struct switching_rule *rule;
3939
Willy Tarreaub099aca2008-10-12 17:26:37 +02003940 if (curproxy == &defproxy) {
3941 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003942 err_code |= ERR_ALERT | ERR_FATAL;
3943 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003944 }
3945
Willy Tarreau55ea7572007-06-17 19:56:27 +02003946 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003947 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003948
3949 if (*(args[1]) == 0) {
3950 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003951 err_code |= ERR_ALERT | ERR_FATAL;
3952 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003953 }
3954
Willy Tarreauf51658d2014-04-23 01:21:56 +02003955 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
3956 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3957 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3958 file, linenum, errmsg);
3959 err_code |= ERR_ALERT | ERR_FATAL;
3960 goto out;
3961 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02003962
Willy Tarreauf51658d2014-04-23 01:21:56 +02003963 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02003964 }
3965
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003966 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02003967 rule->cond = cond;
3968 rule->be.name = strdup(args[1]);
3969 LIST_INIT(&rule->list);
3970 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
3971 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02003972 else if (strcmp(args[0], "use-server") == 0) {
3973 struct server_rule *rule;
3974
3975 if (curproxy == &defproxy) {
3976 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3977 err_code |= ERR_ALERT | ERR_FATAL;
3978 goto out;
3979 }
3980
3981 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3982 err_code |= ERR_WARN;
3983
3984 if (*(args[1]) == 0) {
3985 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
3986 err_code |= ERR_ALERT | ERR_FATAL;
3987 goto out;
3988 }
3989
3990 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
3991 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
3992 file, linenum, args[0]);
3993 err_code |= ERR_ALERT | ERR_FATAL;
3994 goto out;
3995 }
3996
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003997 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
3998 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
3999 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004000 err_code |= ERR_ALERT | ERR_FATAL;
4001 goto out;
4002 }
4003
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004004 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004005
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004006 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004007 rule->cond = cond;
4008 rule->srv.name = strdup(args[1]);
4009 LIST_INIT(&rule->list);
4010 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4011 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4012 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004013 else if ((!strcmp(args[0], "force-persist")) ||
4014 (!strcmp(args[0], "ignore-persist"))) {
4015 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004016
4017 if (curproxy == &defproxy) {
4018 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4019 err_code |= ERR_ALERT | ERR_FATAL;
4020 goto out;
4021 }
4022
4023 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4024 err_code |= ERR_WARN;
4025
Willy Tarreauef6494c2010-01-28 17:12:36 +01004026 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004027 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4028 file, linenum, args[0]);
4029 err_code |= ERR_ALERT | ERR_FATAL;
4030 goto out;
4031 }
4032
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004033 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4034 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4035 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004036 err_code |= ERR_ALERT | ERR_FATAL;
4037 goto out;
4038 }
4039
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004040 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4041 * where force-persist is applied.
4042 */
4043 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004044
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004045 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004046 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004047 if (!strcmp(args[0], "force-persist")) {
4048 rule->type = PERSIST_TYPE_FORCE;
4049 } else {
4050 rule->type = PERSIST_TYPE_IGNORE;
4051 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004052 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004053 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004054 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004055 else if (!strcmp(args[0], "stick-table")) {
4056 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004057 struct proxy *other;
4058
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004059 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004060 if (other) {
4061 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4062 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4063 err_code |= ERR_ALERT | ERR_FATAL;
4064 goto out;
4065 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004066
Emeric Brun32da3c42010-09-23 18:39:19 +02004067 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004068 curproxy->table.type = (unsigned int)-1;
4069 while (*args[myidx]) {
4070 const char *err;
4071
4072 if (strcmp(args[myidx], "size") == 0) {
4073 myidx++;
4074 if (!*(args[myidx])) {
4075 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4076 file, linenum, args[myidx-1]);
4077 err_code |= ERR_ALERT | ERR_FATAL;
4078 goto out;
4079 }
4080 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4081 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4082 file, linenum, *err, args[myidx-1]);
4083 err_code |= ERR_ALERT | ERR_FATAL;
4084 goto out;
4085 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004086 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004087 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004088 else if (strcmp(args[myidx], "peers") == 0) {
4089 myidx++;
Godbach50523162013-12-11 19:48:57 +08004090 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004091 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4092 file, linenum, args[myidx-1]);
4093 err_code |= ERR_ALERT | ERR_FATAL;
4094 goto out;
Godbach50523162013-12-11 19:48:57 +08004095 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004096 curproxy->table.peers.name = strdup(args[myidx++]);
4097 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004098 else if (strcmp(args[myidx], "expire") == 0) {
4099 myidx++;
4100 if (!*(args[myidx])) {
4101 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4102 file, linenum, args[myidx-1]);
4103 err_code |= ERR_ALERT | ERR_FATAL;
4104 goto out;
4105 }
4106 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4107 if (err) {
4108 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4109 file, linenum, *err, args[myidx-1]);
4110 err_code |= ERR_ALERT | ERR_FATAL;
4111 goto out;
4112 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004113 if (val > INT_MAX) {
4114 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4115 file, linenum, val);
4116 err_code |= ERR_ALERT | ERR_FATAL;
4117 goto out;
4118 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004119 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004120 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004121 }
4122 else if (strcmp(args[myidx], "nopurge") == 0) {
4123 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004124 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004125 }
4126 else if (strcmp(args[myidx], "type") == 0) {
4127 myidx++;
4128 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4129 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4130 file, linenum, args[myidx]);
4131 err_code |= ERR_ALERT | ERR_FATAL;
4132 goto out;
4133 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004134 /* myidx already points to next arg */
4135 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004136 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004137 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004138 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004139
4140 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004141 nw = args[myidx];
4142 while (*nw) {
4143 /* the "store" keyword supports a comma-separated list */
4144 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004145 sa = NULL; /* store arg */
4146 while (*nw && *nw != ',') {
4147 if (*nw == '(') {
4148 *nw = 0;
4149 sa = ++nw;
4150 while (*nw != ')') {
4151 if (!*nw) {
4152 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4153 file, linenum, args[0], cw);
4154 err_code |= ERR_ALERT | ERR_FATAL;
4155 goto out;
4156 }
4157 nw++;
4158 }
4159 *nw = '\0';
4160 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004161 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004162 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004163 if (*nw)
4164 *nw++ = '\0';
4165 type = stktable_get_data_type(cw);
4166 if (type < 0) {
4167 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4168 file, linenum, args[0], cw);
4169 err_code |= ERR_ALERT | ERR_FATAL;
4170 goto out;
4171 }
Willy Tarreauac782882010-06-20 10:41:54 +02004172
4173 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4174 switch (err) {
4175 case PE_NONE: break;
4176 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004177 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4178 file, linenum, args[0], cw);
4179 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004180 break;
4181
4182 case PE_ARG_MISSING:
4183 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4184 file, linenum, args[0], cw);
4185 err_code |= ERR_ALERT | ERR_FATAL;
4186 goto out;
4187
4188 case PE_ARG_NOT_USED:
4189 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4190 file, linenum, args[0], cw);
4191 err_code |= ERR_ALERT | ERR_FATAL;
4192 goto out;
4193
4194 default:
4195 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4196 file, linenum, args[0], cw);
4197 err_code |= ERR_ALERT | ERR_FATAL;
4198 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004199 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004200 }
4201 myidx++;
4202 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004203 else {
4204 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4205 file, linenum, args[myidx]);
4206 err_code |= ERR_ALERT | ERR_FATAL;
4207 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004208 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004209 }
4210
4211 if (!curproxy->table.size) {
4212 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4213 file, linenum);
4214 err_code |= ERR_ALERT | ERR_FATAL;
4215 goto out;
4216 }
4217
4218 if (curproxy->table.type == (unsigned int)-1) {
4219 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4220 file, linenum);
4221 err_code |= ERR_ALERT | ERR_FATAL;
4222 goto out;
4223 }
4224 }
4225 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004226 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004227 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004228 int myidx = 0;
4229 const char *name = NULL;
4230 int flags;
4231
4232 if (curproxy == &defproxy) {
4233 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4234 err_code |= ERR_ALERT | ERR_FATAL;
4235 goto out;
4236 }
4237
4238 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4239 err_code |= ERR_WARN;
4240 goto out;
4241 }
4242
4243 myidx++;
4244 if ((strcmp(args[myidx], "store") == 0) ||
4245 (strcmp(args[myidx], "store-request") == 0)) {
4246 myidx++;
4247 flags = STK_IS_STORE;
4248 }
4249 else if (strcmp(args[myidx], "store-response") == 0) {
4250 myidx++;
4251 flags = STK_IS_STORE | STK_ON_RSP;
4252 }
4253 else if (strcmp(args[myidx], "match") == 0) {
4254 myidx++;
4255 flags = STK_IS_MATCH;
4256 }
4257 else if (strcmp(args[myidx], "on") == 0) {
4258 myidx++;
4259 flags = STK_IS_MATCH | STK_IS_STORE;
4260 }
4261 else {
4262 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4263 err_code |= ERR_ALERT | ERR_FATAL;
4264 goto out;
4265 }
4266
4267 if (*(args[myidx]) == 0) {
4268 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4269 err_code |= ERR_ALERT | ERR_FATAL;
4270 goto out;
4271 }
4272
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004273 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004274 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004275 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004276 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004277 err_code |= ERR_ALERT | ERR_FATAL;
4278 goto out;
4279 }
4280
4281 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004282 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4283 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4284 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004285 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004286 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004287 goto out;
4288 }
4289 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004290 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4291 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4292 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004293 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004294 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004295 goto out;
4296 }
4297 }
4298
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004299 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004300 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004301
Emeric Brunb982a3d2010-01-04 15:45:53 +01004302 if (strcmp(args[myidx], "table") == 0) {
4303 myidx++;
4304 name = args[myidx++];
4305 }
4306
Willy Tarreauef6494c2010-01-28 17:12:36 +01004307 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004308 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4309 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4310 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004311 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004312 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004313 goto out;
4314 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004315 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004316 else if (*(args[myidx])) {
4317 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4318 file, linenum, args[0], args[myidx]);
4319 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004320 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004321 goto out;
4322 }
Emeric Brun97679e72010-09-23 17:56:44 +02004323 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004324 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004325 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004326 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004327
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004328 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004329 rule->cond = cond;
4330 rule->expr = expr;
4331 rule->flags = flags;
4332 rule->table.name = name ? strdup(name) : NULL;
4333 LIST_INIT(&rule->list);
4334 if (flags & STK_ON_RSP)
4335 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4336 else
4337 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4338 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004339 else if (!strcmp(args[0], "stats")) {
4340 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4341 curproxy->uri_auth = NULL; /* we must detach from the default config */
4342
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004343 if (!*args[1]) {
4344 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004345 } else if (!strcmp(args[1], "admin")) {
4346 struct stats_admin_rule *rule;
4347
4348 if (curproxy == &defproxy) {
4349 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4350 err_code |= ERR_ALERT | ERR_FATAL;
4351 goto out;
4352 }
4353
4354 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4355 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4356 err_code |= ERR_ALERT | ERR_ABORT;
4357 goto out;
4358 }
4359
4360 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4361 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4362 file, linenum, args[0], args[1]);
4363 err_code |= ERR_ALERT | ERR_FATAL;
4364 goto out;
4365 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004366 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4367 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4368 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004369 err_code |= ERR_ALERT | ERR_FATAL;
4370 goto out;
4371 }
4372
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004373 err_code |= warnif_cond_conflicts(cond,
4374 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4375 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004376
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004377 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004378 rule->cond = cond;
4379 LIST_INIT(&rule->list);
4380 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004381 } else if (!strcmp(args[1], "uri")) {
4382 if (*(args[2]) == 0) {
4383 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004384 err_code |= ERR_ALERT | ERR_FATAL;
4385 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004386 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4387 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004388 err_code |= ERR_ALERT | ERR_ABORT;
4389 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004390 }
4391 } else if (!strcmp(args[1], "realm")) {
4392 if (*(args[2]) == 0) {
4393 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004394 err_code |= ERR_ALERT | ERR_FATAL;
4395 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004396 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4397 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004398 err_code |= ERR_ALERT | ERR_ABORT;
4399 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004400 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004401 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004402 unsigned interval;
4403
4404 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4405 if (err) {
4406 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4407 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004408 err_code |= ERR_ALERT | ERR_FATAL;
4409 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004410 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4411 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004412 err_code |= ERR_ALERT | ERR_ABORT;
4413 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004414 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004415 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004416 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004417
4418 if (curproxy == &defproxy) {
4419 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4420 err_code |= ERR_ALERT | ERR_FATAL;
4421 goto out;
4422 }
4423
4424 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4425 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4426 err_code |= ERR_ALERT | ERR_ABORT;
4427 goto out;
4428 }
4429
Willy Tarreauff011f22011-01-06 17:51:27 +01004430 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004431 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004432 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4433 file, linenum, args[0]);
4434 err_code |= ERR_WARN;
4435 }
4436
Willy Tarreauff011f22011-01-06 17:51:27 +01004437 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004438
Willy Tarreauff011f22011-01-06 17:51:27 +01004439 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004440 err_code |= ERR_ALERT | ERR_ABORT;
4441 goto out;
4442 }
4443
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004444 err_code |= warnif_cond_conflicts(rule->cond,
4445 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4446 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004447 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004448
Willy Tarreaubaaee002006-06-26 02:48:02 +02004449 } else if (!strcmp(args[1], "auth")) {
4450 if (*(args[2]) == 0) {
4451 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004452 err_code |= ERR_ALERT | ERR_FATAL;
4453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004454 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4455 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004456 err_code |= ERR_ALERT | ERR_ABORT;
4457 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004458 }
4459 } else if (!strcmp(args[1], "scope")) {
4460 if (*(args[2]) == 0) {
4461 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004462 err_code |= ERR_ALERT | ERR_FATAL;
4463 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004464 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4465 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004466 err_code |= ERR_ALERT | ERR_ABORT;
4467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004468 }
4469 } else if (!strcmp(args[1], "enable")) {
4470 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4471 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004472 err_code |= ERR_ALERT | ERR_ABORT;
4473 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004474 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004475 } else if (!strcmp(args[1], "hide-version")) {
4476 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4477 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004478 err_code |= ERR_ALERT | ERR_ABORT;
4479 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004480 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004481 } else if (!strcmp(args[1], "show-legends")) {
4482 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4483 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4484 err_code |= ERR_ALERT | ERR_ABORT;
4485 goto out;
4486 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004487 } else if (!strcmp(args[1], "show-node")) {
4488
4489 if (*args[2]) {
4490 int i;
4491 char c;
4492
4493 for (i=0; args[2][i]; i++) {
4494 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004495 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4496 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004497 break;
4498 }
4499
4500 if (!i || args[2][i]) {
4501 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4502 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4503 file, linenum, args[0], args[1]);
4504 err_code |= ERR_ALERT | ERR_FATAL;
4505 goto out;
4506 }
4507 }
4508
4509 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4510 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4511 err_code |= ERR_ALERT | ERR_ABORT;
4512 goto out;
4513 }
4514 } else if (!strcmp(args[1], "show-desc")) {
4515 char *desc = NULL;
4516
4517 if (*args[2]) {
4518 int i, len=0;
4519 char *d;
4520
Willy Tarreau348acfe2014-04-14 15:00:39 +02004521 for (i = 2; *args[i]; i++)
4522 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004523
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004524 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004525
Willy Tarreau348acfe2014-04-14 15:00:39 +02004526 d += snprintf(d, desc + len - d, "%s", args[2]);
4527 for (i = 3; *args[i]; i++)
4528 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004529 }
4530
4531 if (!*args[2] && !global.desc)
4532 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4533 file, linenum, args[1]);
4534 else {
4535 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4536 free(desc);
4537 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4538 err_code |= ERR_ALERT | ERR_ABORT;
4539 goto out;
4540 }
4541 free(desc);
4542 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004543 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004544stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004545 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 +01004546 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004547 err_code |= ERR_ALERT | ERR_FATAL;
4548 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004549 }
4550 }
4551 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004552 int optnum;
4553
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004554 if (*(args[1]) == '\0') {
4555 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4556 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004557 err_code |= ERR_ALERT | ERR_FATAL;
4558 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004559 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004560
4561 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4562 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004563 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4564 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4565 file, linenum, cfg_opts[optnum].name);
4566 err_code |= ERR_ALERT | ERR_FATAL;
4567 goto out;
4568 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004569 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4570 goto out;
4571
Willy Tarreau93893792009-07-23 13:19:11 +02004572 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4573 err_code |= ERR_WARN;
4574 goto out;
4575 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004576
Willy Tarreau3842f002009-06-14 11:39:52 +02004577 curproxy->no_options &= ~cfg_opts[optnum].val;
4578 curproxy->options &= ~cfg_opts[optnum].val;
4579
4580 switch (kwm) {
4581 case KWM_STD:
4582 curproxy->options |= cfg_opts[optnum].val;
4583 break;
4584 case KWM_NO:
4585 curproxy->no_options |= cfg_opts[optnum].val;
4586 break;
4587 case KWM_DEF: /* already cleared */
4588 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004589 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004590
Willy Tarreau93893792009-07-23 13:19:11 +02004591 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004592 }
4593 }
4594
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004595 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4596 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004597 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4598 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4599 file, linenum, cfg_opts2[optnum].name);
4600 err_code |= ERR_ALERT | ERR_FATAL;
4601 goto out;
4602 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004603 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4604 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004605 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4606 err_code |= ERR_WARN;
4607 goto out;
4608 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004609
Willy Tarreau3842f002009-06-14 11:39:52 +02004610 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4611 curproxy->options2 &= ~cfg_opts2[optnum].val;
4612
4613 switch (kwm) {
4614 case KWM_STD:
4615 curproxy->options2 |= cfg_opts2[optnum].val;
4616 break;
4617 case KWM_NO:
4618 curproxy->no_options2 |= cfg_opts2[optnum].val;
4619 break;
4620 case KWM_DEF: /* already cleared */
4621 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004622 }
Willy Tarreau93893792009-07-23 13:19:11 +02004623 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004624 }
4625 }
4626
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004627 /* HTTP options override each other. They can be cancelled using
4628 * "no option xxx" which only switches to default mode if the mode
4629 * was this one (useful for cancelling options set in defaults
4630 * sections).
4631 */
4632 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004633 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4634 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004635 if (kwm == KWM_STD) {
4636 curproxy->options &= ~PR_O_HTTP_MODE;
4637 curproxy->options |= PR_O_HTTP_PCL;
4638 goto out;
4639 }
4640 else if (kwm == KWM_NO) {
4641 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4642 curproxy->options &= ~PR_O_HTTP_MODE;
4643 goto out;
4644 }
4645 }
4646 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004647 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4648 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004649 if (kwm == KWM_STD) {
4650 curproxy->options &= ~PR_O_HTTP_MODE;
4651 curproxy->options |= PR_O_HTTP_FCL;
4652 goto out;
4653 }
4654 else if (kwm == KWM_NO) {
4655 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4656 curproxy->options &= ~PR_O_HTTP_MODE;
4657 goto out;
4658 }
4659 }
4660 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004661 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4662 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004663 if (kwm == KWM_STD) {
4664 curproxy->options &= ~PR_O_HTTP_MODE;
4665 curproxy->options |= PR_O_HTTP_SCL;
4666 goto out;
4667 }
4668 else if (kwm == KWM_NO) {
4669 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4670 curproxy->options &= ~PR_O_HTTP_MODE;
4671 goto out;
4672 }
4673 }
4674 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004675 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4676 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004677 if (kwm == KWM_STD) {
4678 curproxy->options &= ~PR_O_HTTP_MODE;
4679 curproxy->options |= PR_O_HTTP_KAL;
4680 goto out;
4681 }
4682 else if (kwm == KWM_NO) {
4683 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4684 curproxy->options &= ~PR_O_HTTP_MODE;
4685 goto out;
4686 }
4687 }
4688 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004689 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4690 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004691 if (kwm == KWM_STD) {
4692 curproxy->options &= ~PR_O_HTTP_MODE;
4693 curproxy->options |= PR_O_HTTP_TUN;
4694 goto out;
4695 }
4696 else if (kwm == KWM_NO) {
4697 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4698 curproxy->options &= ~PR_O_HTTP_MODE;
4699 goto out;
4700 }
4701 }
4702
Joseph Lynch726ab712015-05-11 23:25:34 -07004703 /* Redispatch can take an integer argument that control when the
4704 * resispatch occurs. All values are relative to the retries option.
4705 * This can be cancelled using "no option xxx".
4706 */
4707 if (strcmp(args[1], "redispatch") == 0) {
4708 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4709 err_code |= ERR_WARN;
4710 goto out;
4711 }
4712
4713 curproxy->no_options &= ~PR_O_REDISP;
4714 curproxy->options &= ~PR_O_REDISP;
4715
4716 switch (kwm) {
4717 case KWM_STD:
4718 curproxy->options |= PR_O_REDISP;
4719 curproxy->redispatch_after = -1;
4720 if(*args[2]) {
4721 curproxy->redispatch_after = atol(args[2]);
4722 }
4723 break;
4724 case KWM_NO:
4725 curproxy->no_options |= PR_O_REDISP;
4726 curproxy->redispatch_after = 0;
4727 break;
4728 case KWM_DEF: /* already cleared */
4729 break;
4730 }
4731 goto out;
4732 }
4733
Willy Tarreau3842f002009-06-14 11:39:52 +02004734 if (kwm != KWM_STD) {
4735 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004736 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004737 err_code |= ERR_ALERT | ERR_FATAL;
4738 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004739 }
4740
Emeric Brun3a058f32009-06-30 18:26:00 +02004741 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004742 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004743 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004744 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004745 if (*(args[2]) != '\0') {
4746 if (!strcmp(args[2], "clf")) {
4747 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004748 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004749 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004750 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004751 err_code |= ERR_ALERT | ERR_FATAL;
4752 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004753 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004754 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4755 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004756 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004757 if (curproxy->conf.logformat_string != default_http_log_format &&
4758 curproxy->conf.logformat_string != default_tcp_log_format &&
4759 curproxy->conf.logformat_string != clf_http_log_format)
4760 free(curproxy->conf.logformat_string);
4761 curproxy->conf.logformat_string = logformat;
4762
4763 free(curproxy->conf.lfs_file);
4764 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4765 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004766 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004767 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004768 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004769 if (curproxy->conf.logformat_string != default_http_log_format &&
4770 curproxy->conf.logformat_string != default_tcp_log_format &&
4771 curproxy->conf.logformat_string != clf_http_log_format)
4772 free(curproxy->conf.logformat_string);
4773 curproxy->conf.logformat_string = default_tcp_log_format;
4774
4775 free(curproxy->conf.lfs_file);
4776 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4777 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004778
4779 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4780 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004781 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004782 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004783 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004784 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004785 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004786
William Lallemanddf1425a2015-04-28 20:17:49 +02004787 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4788 goto out;
4789
Willy Tarreau13943ab2006-12-31 00:24:10 +01004790 if (curproxy->cap & PR_CAP_FE)
4791 curproxy->options |= PR_O_TCP_CLI_KA;
4792 if (curproxy->cap & PR_CAP_BE)
4793 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004794 }
4795 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004796 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004797 err_code |= ERR_WARN;
4798
Willy Tarreaubaaee002006-06-26 02:48:02 +02004799 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004800 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004801 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004802 curproxy->options2 &= ~PR_O2_CHK_ANY;
4803 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004804 if (!*args[2]) { /* no argument */
4805 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4806 curproxy->check_len = strlen(DEF_CHECK_REQ);
4807 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004808 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004809 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004810 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004811 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004812 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004813 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 if (*args[4])
4815 reqlen += strlen(args[4]);
4816 else
4817 reqlen += strlen("HTTP/1.0");
4818
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004819 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004820 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004821 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004822 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004823 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4824 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004825 }
4826 else if (!strcmp(args[1], "ssl-hello-chk")) {
4827 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004828 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004829 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004830
Willy Tarreaua534fea2008-08-03 12:19:50 +02004831 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004832 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004833 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004834 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004835
4836 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004838 }
Willy Tarreau23677902007-05-08 23:50:35 +02004839 else if (!strcmp(args[1], "smtpchk")) {
4840 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004841 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004842 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004843 curproxy->options2 &= ~PR_O2_CHK_ANY;
4844 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004845
4846 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4847 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4848 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4849 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4850 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4851 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004852 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004853 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4854 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4855 } else {
4856 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4857 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4858 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4859 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4860 }
4861 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004862 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4863 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004864 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004865 else if (!strcmp(args[1], "pgsql-check")) {
4866 /* use PostgreSQL request to check servers' health */
4867 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4868 err_code |= ERR_WARN;
4869
4870 free(curproxy->check_req);
4871 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004872 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004873 curproxy->options2 |= PR_O2_PGSQL_CHK;
4874
4875 if (*(args[2])) {
4876 int cur_arg = 2;
4877
4878 while (*(args[cur_arg])) {
4879 if (strcmp(args[cur_arg], "user") == 0) {
4880 char * packet;
4881 uint32_t packet_len;
4882 uint32_t pv;
4883
4884 /* suboption header - needs additional argument for it */
4885 if (*(args[cur_arg+1]) == 0) {
4886 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4887 file, linenum, args[0], args[1], args[cur_arg]);
4888 err_code |= ERR_ALERT | ERR_FATAL;
4889 goto out;
4890 }
4891
4892 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4893 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4894 pv = htonl(0x30000); /* protocol version 3.0 */
4895
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004896 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004897
4898 memcpy(packet + 4, &pv, 4);
4899
4900 /* copy "user" */
4901 memcpy(packet + 8, "user", 4);
4902
4903 /* copy username */
4904 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4905
4906 free(curproxy->check_req);
4907 curproxy->check_req = packet;
4908 curproxy->check_len = packet_len;
4909
4910 packet_len = htonl(packet_len);
4911 memcpy(packet, &packet_len, 4);
4912 cur_arg += 2;
4913 } else {
4914 /* unknown suboption - catchall */
4915 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4916 file, linenum, args[0], args[1]);
4917 err_code |= ERR_ALERT | ERR_FATAL;
4918 goto out;
4919 }
4920 } /* end while loop */
4921 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004922 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4923 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004924 }
4925
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004926 else if (!strcmp(args[1], "redis-check")) {
4927 /* use REDIS PING request to check servers' health */
4928 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4929 err_code |= ERR_WARN;
4930
4931 free(curproxy->check_req);
4932 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004933 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004934 curproxy->options2 |= PR_O2_REDIS_CHK;
4935
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004936 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004937 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4938 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004939
4940 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4941 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004942 }
4943
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004944 else if (!strcmp(args[1], "mysql-check")) {
4945 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004946 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4947 err_code |= ERR_WARN;
4948
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004949 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004950 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004951 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004952 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004953
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004954 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004955 * const char mysql40_client_auth_pkt[] = {
4956 * "\x0e\x00\x00" // packet length
4957 * "\x01" // packet number
4958 * "\x00\x00" // client capabilities
4959 * "\x00\x00\x01" // max packet
4960 * "haproxy\x00" // username (null terminated string)
4961 * "\x00" // filler (always 0x00)
4962 * "\x01\x00\x00" // packet length
4963 * "\x00" // packet number
4964 * "\x01" // COM_QUIT command
4965 * };
4966 */
4967
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02004968 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
4969 * const char mysql41_client_auth_pkt[] = {
4970 * "\x0e\x00\x00\" // packet length
4971 * "\x01" // packet number
4972 * "\x00\x00\x00\x00" // client capabilities
4973 * "\x00\x00\x00\x01" // max packet
4974 * "\x21" // character set (UTF-8)
4975 * char[23] // All zeroes
4976 * "haproxy\x00" // username (null terminated string)
4977 * "\x00" // filler (always 0x00)
4978 * "\x01\x00\x00" // packet length
4979 * "\x00" // packet number
4980 * "\x01" // COM_QUIT command
4981 * };
4982 */
4983
4984
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004985 if (*(args[2])) {
4986 int cur_arg = 2;
4987
4988 while (*(args[cur_arg])) {
4989 if (strcmp(args[cur_arg], "user") == 0) {
4990 char *mysqluser;
4991 int packetlen, reqlen, userlen;
4992
4993 /* suboption header - needs additional argument for it */
4994 if (*(args[cur_arg+1]) == 0) {
4995 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4996 file, linenum, args[0], args[1], args[cur_arg]);
4997 err_code |= ERR_ALERT | ERR_FATAL;
4998 goto out;
4999 }
5000 mysqluser = args[cur_arg + 1];
5001 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005002
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005003 if (*(args[cur_arg+2])) {
5004 if (!strcmp(args[cur_arg+2], "post-41")) {
5005 packetlen = userlen + 7 + 27;
5006 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005007
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005008 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005009 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005010 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005011
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005012 snprintf(curproxy->check_req, 4, "%c%c%c",
5013 ((unsigned char) packetlen & 0xff),
5014 ((unsigned char) (packetlen >> 8) & 0xff),
5015 ((unsigned char) (packetlen >> 16) & 0xff));
5016
5017 curproxy->check_req[3] = 1;
5018 curproxy->check_req[5] = 130;
5019 curproxy->check_req[11] = 1;
5020 curproxy->check_req[12] = 33;
5021 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5022 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5023 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5024 cur_arg += 3;
5025 } else {
5026 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5027 err_code |= ERR_ALERT | ERR_FATAL;
5028 goto out;
5029 }
5030 } else {
5031 packetlen = userlen + 7;
5032 reqlen = packetlen + 9;
5033
5034 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005035 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005036 curproxy->check_len = reqlen;
5037
5038 snprintf(curproxy->check_req, 4, "%c%c%c",
5039 ((unsigned char) packetlen & 0xff),
5040 ((unsigned char) (packetlen >> 8) & 0xff),
5041 ((unsigned char) (packetlen >> 16) & 0xff));
5042
5043 curproxy->check_req[3] = 1;
5044 curproxy->check_req[5] = 128;
5045 curproxy->check_req[8] = 1;
5046 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5047 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5048 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5049 cur_arg += 2;
5050 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005051 } else {
5052 /* unknown suboption - catchall */
5053 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5054 file, linenum, args[0], args[1]);
5055 err_code |= ERR_ALERT | ERR_FATAL;
5056 goto out;
5057 }
5058 } /* end while loop */
5059 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005060 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005061 else if (!strcmp(args[1], "ldap-check")) {
5062 /* use LDAP request to check servers' health */
5063 free(curproxy->check_req);
5064 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005065 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005066 curproxy->options2 |= PR_O2_LDAP_CHK;
5067
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005068 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005069 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5070 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005071 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5072 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005073 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005074 else if (!strcmp(args[1], "tcp-check")) {
5075 /* use raw TCPCHK send/expect to check servers' health */
5076 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5077 err_code |= ERR_WARN;
5078
5079 free(curproxy->check_req);
5080 curproxy->check_req = NULL;
5081 curproxy->options2 &= ~PR_O2_CHK_ANY;
5082 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005083 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5084 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005085 }
Simon Horman98637e52014-06-20 12:30:16 +09005086 else if (!strcmp(args[1], "external-check")) {
5087 /* excute an external command to check servers' health */
5088 free(curproxy->check_req);
5089 curproxy->check_req = NULL;
5090 curproxy->options2 &= ~PR_O2_CHK_ANY;
5091 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005092 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5093 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005094 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005095 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005096 int cur_arg;
5097
5098 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5099 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005100 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005101
Willy Tarreau87cf5142011-08-19 22:57:24 +02005102 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005103
5104 free(curproxy->fwdfor_hdr_name);
5105 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5106 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5107
5108 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5109 cur_arg = 2;
5110 while (*(args[cur_arg])) {
5111 if (!strcmp(args[cur_arg], "except")) {
5112 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005113 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005114 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5115 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005116 err_code |= ERR_ALERT | ERR_FATAL;
5117 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005118 }
5119 /* flush useless bits */
5120 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005121 cur_arg += 2;
5122 } else if (!strcmp(args[cur_arg], "header")) {
5123 /* suboption header - needs additional argument for it */
5124 if (*(args[cur_arg+1]) == 0) {
5125 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5126 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005127 err_code |= ERR_ALERT | ERR_FATAL;
5128 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005129 }
5130 free(curproxy->fwdfor_hdr_name);
5131 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5132 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5133 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005134 } else if (!strcmp(args[cur_arg], "if-none")) {
5135 curproxy->options &= ~PR_O_FF_ALWAYS;
5136 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005137 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005138 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005139 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005140 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005141 err_code |= ERR_ALERT | ERR_FATAL;
5142 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005143 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005144 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005145 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005146 else if (!strcmp(args[1], "originalto")) {
5147 int cur_arg;
5148
5149 /* insert x-original-to field, but not for the IP address listed as an except.
5150 * set default options (ie: bitfield, header name, etc)
5151 */
5152
5153 curproxy->options |= PR_O_ORGTO;
5154
5155 free(curproxy->orgto_hdr_name);
5156 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5157 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5158
Willy Tarreau87cf5142011-08-19 22:57:24 +02005159 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005160 cur_arg = 2;
5161 while (*(args[cur_arg])) {
5162 if (!strcmp(args[cur_arg], "except")) {
5163 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005164 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 +02005165 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5166 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005167 err_code |= ERR_ALERT | ERR_FATAL;
5168 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005169 }
5170 /* flush useless bits */
5171 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5172 cur_arg += 2;
5173 } else if (!strcmp(args[cur_arg], "header")) {
5174 /* suboption header - needs additional argument for it */
5175 if (*(args[cur_arg+1]) == 0) {
5176 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5177 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005178 err_code |= ERR_ALERT | ERR_FATAL;
5179 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005180 }
5181 free(curproxy->orgto_hdr_name);
5182 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5183 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5184 cur_arg += 2;
5185 } else {
5186 /* unknown suboption - catchall */
5187 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5188 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005189 err_code |= ERR_ALERT | ERR_FATAL;
5190 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005191 }
5192 } /* end while loop */
5193 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005194 else {
5195 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005196 err_code |= ERR_ALERT | ERR_FATAL;
5197 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005198 }
Willy Tarreau93893792009-07-23 13:19:11 +02005199 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005200 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005201 else if (!strcmp(args[0], "default_backend")) {
5202 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005203 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005204
5205 if (*(args[1]) == 0) {
5206 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005207 err_code |= ERR_ALERT | ERR_FATAL;
5208 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005209 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005210 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005211 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005212
5213 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5214 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005215 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005216 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005217 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005218 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005219
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005220 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5221 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 +01005222 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005223 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005224 /* enable reconnections to dispatch */
5225 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005226
5227 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5228 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005229 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005230 else if (!strcmp(args[0], "http-reuse")) {
5231 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5232 err_code |= ERR_WARN;
5233
5234 if (strcmp(args[1], "never") == 0) {
5235 /* enable a graceful server shutdown on an HTTP 404 response */
5236 curproxy->options &= ~PR_O_REUSE_MASK;
5237 curproxy->options |= PR_O_REUSE_NEVR;
5238 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5239 goto out;
5240 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005241 else if (strcmp(args[1], "safe") == 0) {
5242 /* enable a graceful server shutdown on an HTTP 404 response */
5243 curproxy->options &= ~PR_O_REUSE_MASK;
5244 curproxy->options |= PR_O_REUSE_SAFE;
5245 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5246 goto out;
5247 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005248 else if (strcmp(args[1], "aggressive") == 0) {
5249 curproxy->options &= ~PR_O_REUSE_MASK;
5250 curproxy->options |= PR_O_REUSE_AGGR;
5251 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5252 goto out;
5253 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005254 else if (strcmp(args[1], "always") == 0) {
5255 /* enable a graceful server shutdown on an HTTP 404 response */
5256 curproxy->options &= ~PR_O_REUSE_MASK;
5257 curproxy->options |= PR_O_REUSE_ALWS;
5258 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5259 goto out;
5260 }
5261 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005262 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005263 err_code |= ERR_ALERT | ERR_FATAL;
5264 goto out;
5265 }
5266 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005267 else if (!strcmp(args[0], "http-check")) {
5268 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005270
5271 if (strcmp(args[1], "disable-on-404") == 0) {
5272 /* enable a graceful server shutdown on an HTTP 404 response */
5273 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005274 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5275 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005276 }
Willy Tarreauef781042010-01-27 11:53:01 +01005277 else if (strcmp(args[1], "send-state") == 0) {
5278 /* enable emission of the apparent state of a server in HTTP checks */
5279 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005280 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5281 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005282 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005283 else if (strcmp(args[1], "expect") == 0) {
5284 const char *ptr_arg;
5285 int cur_arg;
5286
5287 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5288 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5289 err_code |= ERR_ALERT | ERR_FATAL;
5290 goto out;
5291 }
5292
5293 cur_arg = 2;
5294 /* consider exclamation marks, sole or at the beginning of a word */
5295 while (*(ptr_arg = args[cur_arg])) {
5296 while (*ptr_arg == '!') {
5297 curproxy->options2 ^= PR_O2_EXP_INV;
5298 ptr_arg++;
5299 }
5300 if (*ptr_arg)
5301 break;
5302 cur_arg++;
5303 }
5304 /* now ptr_arg points to the beginning of a word past any possible
5305 * exclamation mark, and cur_arg is the argument which holds this word.
5306 */
5307 if (strcmp(ptr_arg, "status") == 0) {
5308 if (!*(args[cur_arg + 1])) {
5309 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5310 file, linenum, args[0], args[1], ptr_arg);
5311 err_code |= ERR_ALERT | ERR_FATAL;
5312 goto out;
5313 }
5314 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005315 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005316 curproxy->expect_str = strdup(args[cur_arg + 1]);
5317 }
5318 else if (strcmp(ptr_arg, "string") == 0) {
5319 if (!*(args[cur_arg + 1])) {
5320 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5321 file, linenum, args[0], args[1], ptr_arg);
5322 err_code |= ERR_ALERT | ERR_FATAL;
5323 goto out;
5324 }
5325 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005326 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005327 curproxy->expect_str = strdup(args[cur_arg + 1]);
5328 }
5329 else if (strcmp(ptr_arg, "rstatus") == 0) {
5330 if (!*(args[cur_arg + 1])) {
5331 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5332 file, linenum, args[0], args[1], ptr_arg);
5333 err_code |= ERR_ALERT | ERR_FATAL;
5334 goto out;
5335 }
5336 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005337 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005338 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005339 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005340 free(curproxy->expect_regex);
5341 curproxy->expect_regex = NULL;
5342 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005343 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005344 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5345 error = NULL;
5346 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5347 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5348 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5349 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005350 err_code |= ERR_ALERT | ERR_FATAL;
5351 goto out;
5352 }
5353 }
5354 else if (strcmp(ptr_arg, "rstring") == 0) {
5355 if (!*(args[cur_arg + 1])) {
5356 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5357 file, linenum, args[0], args[1], ptr_arg);
5358 err_code |= ERR_ALERT | ERR_FATAL;
5359 goto out;
5360 }
5361 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005362 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005363 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005364 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005365 free(curproxy->expect_regex);
5366 curproxy->expect_regex = NULL;
5367 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005368 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005369 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5370 error = NULL;
5371 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5372 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5373 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5374 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005375 err_code |= ERR_ALERT | ERR_FATAL;
5376 goto out;
5377 }
5378 }
5379 else {
5380 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5381 file, linenum, args[0], args[1], ptr_arg);
5382 err_code |= ERR_ALERT | ERR_FATAL;
5383 goto out;
5384 }
5385 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005386 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005387 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 +02005388 err_code |= ERR_ALERT | ERR_FATAL;
5389 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005390 }
5391 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005392 else if (!strcmp(args[0], "tcp-check")) {
5393 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5394 err_code |= ERR_WARN;
5395
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005396 if (strcmp(args[1], "comment") == 0) {
5397 int cur_arg;
5398 struct tcpcheck_rule *tcpcheck;
5399
5400 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005401 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005402 tcpcheck->action = TCPCHK_ACT_COMMENT;
5403
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
5411 tcpcheck->comment = strdup(args[cur_arg + 1]);
5412
5413 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005414 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5415 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005416 }
5417 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005418 const char *ptr_arg;
5419 int cur_arg;
5420 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005421
5422 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005423 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5424 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5425 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5426 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5427 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005428
Willy Tarreau5581c272015-05-13 12:24:53 +02005429 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5430 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5431 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5432 file, linenum);
5433 err_code |= ERR_ALERT | ERR_FATAL;
5434 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005435 }
5436
5437 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005438 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005439 tcpcheck->action = TCPCHK_ACT_CONNECT;
5440
5441 /* parsing each parameters to fill up the rule */
5442 while (*(ptr_arg = args[cur_arg])) {
5443 /* tcp port */
5444 if (strcmp(args[cur_arg], "port") == 0) {
5445 if ( (atol(args[cur_arg + 1]) > 65535) ||
5446 (atol(args[cur_arg + 1]) < 1) ){
5447 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5448 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5449 err_code |= ERR_ALERT | ERR_FATAL;
5450 goto out;
5451 }
5452 tcpcheck->port = atol(args[cur_arg + 1]);
5453 cur_arg += 2;
5454 }
5455 /* send proxy protocol */
5456 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5457 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5458 cur_arg++;
5459 }
5460#ifdef USE_OPENSSL
5461 else if (strcmp(args[cur_arg], "ssl") == 0) {
5462 curproxy->options |= PR_O_TCPCHK_SSL;
5463 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5464 cur_arg++;
5465 }
5466#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005467 /* comment for this tcpcheck line */
5468 else if (strcmp(args[cur_arg], "comment") == 0) {
5469 if (!*args[cur_arg + 1]) {
5470 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5471 file, linenum, args[cur_arg]);
5472 err_code |= ERR_ALERT | ERR_FATAL;
5473 goto out;
5474 }
5475 tcpcheck->comment = strdup(args[cur_arg + 1]);
5476 cur_arg += 2;
5477 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005478 else {
5479#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005480 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 +01005481#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005482 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 +01005483#endif /* USE_OPENSSL */
5484 file, linenum, args[0], args[1], args[cur_arg]);
5485 err_code |= ERR_ALERT | ERR_FATAL;
5486 goto out;
5487 }
5488
5489 }
5490
5491 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5492 }
5493 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005494 if (! *(args[2]) ) {
5495 /* SEND string expected */
5496 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5497 file, linenum, args[0], args[1], args[2]);
5498 err_code |= ERR_ALERT | ERR_FATAL;
5499 goto out;
5500 } else {
5501 struct tcpcheck_rule *tcpcheck;
5502
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005503 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005504
5505 tcpcheck->action = TCPCHK_ACT_SEND;
5506 tcpcheck->string_len = strlen(args[2]);
5507 tcpcheck->string = strdup(args[2]);
5508 tcpcheck->expect_regex = NULL;
5509
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005510 /* comment for this tcpcheck line */
5511 if (strcmp(args[3], "comment") == 0) {
5512 if (!*args[4]) {
5513 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5514 file, linenum, args[3]);
5515 err_code |= ERR_ALERT | ERR_FATAL;
5516 goto out;
5517 }
5518 tcpcheck->comment = strdup(args[4]);
5519 }
5520
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005521 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5522 }
5523 }
5524 else if (strcmp(args[1], "send-binary") == 0) {
5525 if (! *(args[2]) ) {
5526 /* SEND binary string expected */
5527 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5528 file, linenum, args[0], args[1], args[2]);
5529 err_code |= ERR_ALERT | ERR_FATAL;
5530 goto out;
5531 } else {
5532 struct tcpcheck_rule *tcpcheck;
5533 char *err = NULL;
5534
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005535 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005536
5537 tcpcheck->action = TCPCHK_ACT_SEND;
5538 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5539 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5540 file, linenum, args[0], args[1], args[2], err);
5541 err_code |= ERR_ALERT | ERR_FATAL;
5542 goto out;
5543 }
5544 tcpcheck->expect_regex = NULL;
5545
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005546 /* comment for this tcpcheck line */
5547 if (strcmp(args[3], "comment") == 0) {
5548 if (!*args[4]) {
5549 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5550 file, linenum, args[3]);
5551 err_code |= ERR_ALERT | ERR_FATAL;
5552 goto out;
5553 }
5554 tcpcheck->comment = strdup(args[4]);
5555 }
5556
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005557 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5558 }
5559 }
5560 else if (strcmp(args[1], "expect") == 0) {
5561 const char *ptr_arg;
5562 int cur_arg;
5563 int inverse = 0;
5564
5565 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5566 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5567 err_code |= ERR_ALERT | ERR_FATAL;
5568 goto out;
5569 }
5570
5571 cur_arg = 2;
5572 /* consider exclamation marks, sole or at the beginning of a word */
5573 while (*(ptr_arg = args[cur_arg])) {
5574 while (*ptr_arg == '!') {
5575 inverse = !inverse;
5576 ptr_arg++;
5577 }
5578 if (*ptr_arg)
5579 break;
5580 cur_arg++;
5581 }
5582 /* now ptr_arg points to the beginning of a word past any possible
5583 * exclamation mark, and cur_arg is the argument which holds this word.
5584 */
5585 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005586 struct tcpcheck_rule *tcpcheck;
5587 char *err = NULL;
5588
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005589 if (!*(args[cur_arg + 1])) {
5590 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5591 file, linenum, args[0], args[1], ptr_arg);
5592 err_code |= ERR_ALERT | ERR_FATAL;
5593 goto out;
5594 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005595
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005596 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005597
5598 tcpcheck->action = TCPCHK_ACT_EXPECT;
5599 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5600 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5601 file, linenum, args[0], args[1], args[2], err);
5602 err_code |= ERR_ALERT | ERR_FATAL;
5603 goto out;
5604 }
5605 tcpcheck->expect_regex = NULL;
5606 tcpcheck->inverse = inverse;
5607
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005608 /* tcpcheck comment */
5609 cur_arg += 2;
5610 if (strcmp(args[cur_arg], "comment") == 0) {
5611 if (!*args[cur_arg + 1]) {
5612 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5613 file, linenum, args[cur_arg + 1]);
5614 err_code |= ERR_ALERT | ERR_FATAL;
5615 goto out;
5616 }
5617 tcpcheck->comment = strdup(args[cur_arg + 1]);
5618 }
5619
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005620 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5621 }
5622 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005623 struct tcpcheck_rule *tcpcheck;
5624
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005625 if (!*(args[cur_arg + 1])) {
5626 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5627 file, linenum, args[0], args[1], ptr_arg);
5628 err_code |= ERR_ALERT | ERR_FATAL;
5629 goto out;
5630 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005631
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005632 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005633
5634 tcpcheck->action = TCPCHK_ACT_EXPECT;
5635 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5636 tcpcheck->string = strdup(args[cur_arg + 1]);
5637 tcpcheck->expect_regex = NULL;
5638 tcpcheck->inverse = inverse;
5639
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005640 /* tcpcheck comment */
5641 cur_arg += 2;
5642 if (strcmp(args[cur_arg], "comment") == 0) {
5643 if (!*args[cur_arg + 1]) {
5644 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5645 file, linenum, args[cur_arg + 1]);
5646 err_code |= ERR_ALERT | ERR_FATAL;
5647 goto out;
5648 }
5649 tcpcheck->comment = strdup(args[cur_arg + 1]);
5650 }
5651
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005652 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5653 }
5654 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005655 struct tcpcheck_rule *tcpcheck;
5656
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005657 if (!*(args[cur_arg + 1])) {
5658 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5659 file, linenum, args[0], args[1], ptr_arg);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005663
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005664 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005665
5666 tcpcheck->action = TCPCHK_ACT_EXPECT;
5667 tcpcheck->string_len = 0;
5668 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005669 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5670 error = NULL;
5671 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5672 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5673 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5674 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005675 err_code |= ERR_ALERT | ERR_FATAL;
5676 goto out;
5677 }
5678 tcpcheck->inverse = inverse;
5679
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005680 /* tcpcheck comment */
5681 cur_arg += 2;
5682 if (strcmp(args[cur_arg], "comment") == 0) {
5683 if (!*args[cur_arg + 1]) {
5684 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5685 file, linenum, args[cur_arg + 1]);
5686 err_code |= ERR_ALERT | ERR_FATAL;
5687 goto out;
5688 }
5689 tcpcheck->comment = strdup(args[cur_arg + 1]);
5690 }
5691
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005692 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5693 }
5694 else {
5695 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5696 file, linenum, args[0], args[1], ptr_arg);
5697 err_code |= ERR_ALERT | ERR_FATAL;
5698 goto out;
5699 }
5700 }
5701 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005702 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005703 err_code |= ERR_ALERT | ERR_FATAL;
5704 goto out;
5705 }
5706 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005707 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005708 if (curproxy == &defproxy) {
5709 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005710 err_code |= ERR_ALERT | ERR_FATAL;
5711 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005712 }
5713
Willy Tarreaub80c2302007-11-30 20:51:32 +01005714 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005715 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005716
5717 if (strcmp(args[1], "fail") == 0) {
5718 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005719 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005720 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5721 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005722 err_code |= ERR_ALERT | ERR_FATAL;
5723 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005724 }
5725
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005726 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5727 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5728 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005729 err_code |= ERR_ALERT | ERR_FATAL;
5730 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005731 }
5732 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5733 }
5734 else {
5735 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005736 err_code |= ERR_ALERT | ERR_FATAL;
5737 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005738 }
5739 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005740#ifdef TPROXY
5741 else if (!strcmp(args[0], "transparent")) {
5742 /* enable transparent proxy connections */
5743 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005744 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5745 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005746 }
5747#endif
5748 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005749 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005750 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005751
Willy Tarreaubaaee002006-06-26 02:48:02 +02005752 if (*(args[1]) == 0) {
5753 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005754 err_code |= ERR_ALERT | ERR_FATAL;
5755 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005756 }
5757 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005758 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5759 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005760 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005761 else if (!strcmp(args[0], "backlog")) { /* backlog */
5762 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005763 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005764
5765 if (*(args[1]) == 0) {
5766 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005767 err_code |= ERR_ALERT | ERR_FATAL;
5768 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005769 }
5770 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005771 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5772 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005773 }
Willy Tarreau86034312006-12-29 00:10:33 +01005774 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005775 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005776 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005777
Willy Tarreau86034312006-12-29 00:10:33 +01005778 if (*(args[1]) == 0) {
5779 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005780 err_code |= ERR_ALERT | ERR_FATAL;
5781 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005782 }
5783 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005784 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5785 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005786 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005787 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5788 if (*(args[1]) == 0) {
5789 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005790 err_code |= ERR_ALERT | ERR_FATAL;
5791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005793 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5794 if (err) {
5795 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5796 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005797 err_code |= ERR_ALERT | ERR_FATAL;
5798 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005799 }
5800 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005801 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5802 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005803 }
5804 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005805 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005806 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005807 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005808
Willy Tarreaubaaee002006-06-26 02:48:02 +02005809 if (curproxy == &defproxy) {
5810 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005811 err_code |= ERR_ALERT | ERR_FATAL;
5812 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005813 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005814 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005815 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005816
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005817 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005818 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005819 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005820 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005821 goto out;
5822 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005823
5824 proto = protocol_by_family(sk->ss_family);
5825 if (!proto || !proto->connect) {
5826 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5827 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005828 err_code |= ERR_ALERT | ERR_FATAL;
5829 goto out;
5830 }
5831
5832 if (port1 != port2) {
5833 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5834 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005835 err_code |= ERR_ALERT | ERR_FATAL;
5836 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005837 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005838
5839 if (!port1) {
5840 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5841 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005842 err_code |= ERR_ALERT | ERR_FATAL;
5843 goto out;
5844 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005845
William Lallemanddf1425a2015-04-28 20:17:49 +02005846 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5847 goto out;
5848
Willy Tarreaud5191e72010-02-09 20:50:45 +01005849 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005850 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005851 }
5852 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005853 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005854 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005855
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005856 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5857 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005858 err_code |= ERR_ALERT | ERR_FATAL;
5859 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005860 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005861 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005862 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005863 /**
5864 * The syntax for hash-type config element is
5865 * hash-type {map-based|consistent} [[<algo>] avalanche]
5866 *
5867 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5868 */
5869 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005870
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005871 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5872 err_code |= ERR_WARN;
5873
5874 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005875 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5876 }
5877 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005878 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5879 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005880 else if (strcmp(args[1], "avalanche") == 0) {
5881 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]);
5882 err_code |= ERR_ALERT | ERR_FATAL;
5883 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005884 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005885 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005886 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005887 err_code |= ERR_ALERT | ERR_FATAL;
5888 goto out;
5889 }
Bhaskar98634f02013-10-29 23:30:51 -04005890
5891 /* set the hash function to use */
5892 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005893 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005894 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005895
5896 /* if consistent with no argument, then avalanche modifier is also applied */
5897 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5898 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005899 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005900 /* set the hash function */
5901 if (!strcmp(args[2], "sdbm")) {
5902 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5903 }
5904 else if (!strcmp(args[2], "djb2")) {
5905 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005906 }
5907 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005908 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005909 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005910 else if (!strcmp(args[2], "crc32")) {
5911 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5912 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005913 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005914 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 -05005915 err_code |= ERR_ALERT | ERR_FATAL;
5916 goto out;
5917 }
5918
5919 /* set the hash modifier */
5920 if (!strcmp(args[3], "avalanche")) {
5921 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5922 }
5923 else if (*args[3]) {
5924 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5925 err_code |= ERR_ALERT | ERR_FATAL;
5926 goto out;
5927 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005928 }
William Lallemanda73203e2012-03-12 12:48:57 +01005929 }
William Lallemanda73203e2012-03-12 12:48:57 +01005930 else if (strcmp(args[0], "unique-id-format") == 0) {
5931 if (!*(args[1])) {
5932 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
William Lallemand3203ff42012-11-11 17:30:56 +01005936 if (*(args[2])) {
5937 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5938 err_code |= ERR_ALERT | ERR_FATAL;
5939 goto out;
5940 }
Willy Tarreau62a61232013-04-12 18:13:46 +02005941 free(curproxy->conf.uniqueid_format_string);
5942 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005943
Willy Tarreau62a61232013-04-12 18:13:46 +02005944 free(curproxy->conf.uif_file);
5945 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
5946 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01005947 }
William Lallemanda73203e2012-03-12 12:48:57 +01005948
5949 else if (strcmp(args[0], "unique-id-header") == 0) {
5950 if (!*(args[1])) {
5951 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5952 err_code |= ERR_ALERT | ERR_FATAL;
5953 goto out;
5954 }
5955 free(curproxy->header_unique_id);
5956 curproxy->header_unique_id = strdup(args[1]);
5957 }
5958
William Lallemand723b73a2012-02-08 16:37:49 +01005959 else if (strcmp(args[0], "log-format") == 0) {
5960 if (!*(args[1])) {
5961 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5962 err_code |= ERR_ALERT | ERR_FATAL;
5963 goto out;
5964 }
William Lallemand3203ff42012-11-11 17:30:56 +01005965 if (*(args[2])) {
5966 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5967 err_code |= ERR_ALERT | ERR_FATAL;
5968 goto out;
5969 }
Willy Tarreau196729e2012-05-31 19:30:26 +02005970
Willy Tarreau62a61232013-04-12 18:13:46 +02005971 if (curproxy->conf.logformat_string != default_http_log_format &&
5972 curproxy->conf.logformat_string != default_tcp_log_format &&
5973 curproxy->conf.logformat_string != clf_http_log_format)
5974 free(curproxy->conf.logformat_string);
5975 curproxy->conf.logformat_string = strdup(args[1]);
5976
5977 free(curproxy->conf.lfs_file);
5978 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
5979 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02005980
5981 /* get a chance to improve log-format error reporting by
5982 * reporting the correct line-number when possible.
5983 */
5984 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
5985 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
5986 file, linenum, curproxy->id);
5987 err_code |= ERR_WARN;
5988 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005989 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02005990 else if (!strcmp(args[0], "log-format-sd")) {
5991 if (!*(args[1])) {
5992 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5993 err_code |= ERR_ALERT | ERR_FATAL;
5994 goto out;
5995 }
5996 if (*(args[2])) {
5997 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5998 err_code |= ERR_ALERT | ERR_FATAL;
5999 goto out;
6000 }
6001
6002 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6003 free(curproxy->conf.logformat_sd_string);
6004 curproxy->conf.logformat_sd_string = strdup(args[1]);
6005
6006 free(curproxy->conf.lfsd_file);
6007 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6008 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6009
6010 /* get a chance to improve log-format-sd error reporting by
6011 * reporting the correct line-number when possible.
6012 */
6013 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6014 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6015 file, linenum, curproxy->id);
6016 err_code |= ERR_WARN;
6017 }
6018 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006019 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6020 if (*(args[1]) == 0) {
6021 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6022 err_code |= ERR_ALERT | ERR_FATAL;
6023 goto out;
6024 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006025 chunk_destroy(&curproxy->log_tag);
6026 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006027 }
William Lallemand0f99e342011-10-12 17:50:54 +02006028 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6029 /* delete previous herited or defined syslog servers */
6030 struct logsrv *back;
6031
6032 if (*(args[1]) != 0) {
6033 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6034 err_code |= ERR_ALERT | ERR_FATAL;
6035 goto out;
6036 }
6037
William Lallemand723b73a2012-02-08 16:37:49 +01006038 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6039 LIST_DEL(&tmplogsrv->list);
6040 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006041 }
6042 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006043 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006044 struct logsrv *logsrv;
6045
Willy Tarreaubaaee002006-06-26 02:48:02 +02006046 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006047 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006048 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006049 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006050 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006051 LIST_INIT(&node->list);
6052 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006054 }
6055 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006056 struct sockaddr_storage *sk;
6057 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006058 int arg = 0;
6059 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006060
Vincent Bernat02779b62016-04-03 13:48:43 +02006061 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006062
Willy Tarreau18324f52014-06-27 18:10:07 +02006063 /* just after the address, a length may be specified */
6064 if (strcmp(args[arg+2], "len") == 0) {
6065 len = atoi(args[arg+3]);
6066 if (len < 80 || len > 65535) {
6067 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6068 file, linenum, args[arg+3]);
6069 err_code |= ERR_ALERT | ERR_FATAL;
6070 goto out;
6071 }
6072 logsrv->maxlen = len;
6073
6074 /* skip these two args */
6075 arg += 2;
6076 }
6077 else
6078 logsrv->maxlen = MAX_SYSLOG_LEN;
6079
6080 if (logsrv->maxlen > global.max_syslog_len) {
6081 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006082 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6083 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6084 logline = my_realloc2(logline, global.max_syslog_len + 1);
6085 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006086 }
6087
Dragan Dosen1322d092015-09-22 16:05:32 +02006088 /* after the length, a format may be specified */
6089 if (strcmp(args[arg+2], "format") == 0) {
6090 logsrv->format = get_log_format(args[arg+3]);
6091 if (logsrv->format < 0) {
6092 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6093 err_code |= ERR_ALERT | ERR_FATAL;
6094 goto out;
6095 }
6096
6097 /* skip these two args */
6098 arg += 2;
6099 }
6100
William Lallemanddf1425a2015-04-28 20:17:49 +02006101 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6102 goto out;
6103
Willy Tarreau18324f52014-06-27 18:10:07 +02006104 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006105 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006106 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006107 err_code |= ERR_ALERT | ERR_FATAL;
6108 goto out;
6109
Willy Tarreaubaaee002006-06-26 02:48:02 +02006110 }
6111
William Lallemand0f99e342011-10-12 17:50:54 +02006112 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006113 if (*(args[arg+3])) {
6114 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006115 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006116 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006117 err_code |= ERR_ALERT | ERR_FATAL;
6118 goto out;
6119
Willy Tarreaubaaee002006-06-26 02:48:02 +02006120 }
6121 }
6122
William Lallemand0f99e342011-10-12 17:50:54 +02006123 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006124 if (*(args[arg+4])) {
6125 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006126 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006127 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006128 err_code |= ERR_ALERT | ERR_FATAL;
6129 goto out;
6130
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006131 }
6132 }
6133
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006134 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006135 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006136 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006137 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006138 goto out;
6139 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006140
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006141 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006142
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006143 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006144 if (port1 != port2) {
6145 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6146 file, linenum, args[0], args[1]);
6147 err_code |= ERR_ALERT | ERR_FATAL;
6148 goto out;
6149 }
6150
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006151 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006152 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006153 }
William Lallemand0f99e342011-10-12 17:50:54 +02006154
6155 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006156 }
6157 else {
6158 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6159 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006160 err_code |= ERR_ALERT | ERR_FATAL;
6161 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006162 }
6163 }
6164 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006165 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006166 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006167 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006168 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006169
Willy Tarreau977b8e42006-12-29 14:19:17 +01006170 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006171 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006172
Willy Tarreaubaaee002006-06-26 02:48:02 +02006173 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006174 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6175 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006176 err_code |= ERR_ALERT | ERR_FATAL;
6177 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006178 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006179
6180 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006181 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6182 free(curproxy->conn_src.iface_name);
6183 curproxy->conn_src.iface_name = NULL;
6184 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006185
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006186 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006187 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006188 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006189 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006190 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006191 goto out;
6192 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006193
6194 proto = protocol_by_family(sk->ss_family);
6195 if (!proto || !proto->connect) {
6196 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006197 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006198 err_code |= ERR_ALERT | ERR_FATAL;
6199 goto out;
6200 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006201
6202 if (port1 != port2) {
6203 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6204 file, linenum, args[0], args[1]);
6205 err_code |= ERR_ALERT | ERR_FATAL;
6206 goto out;
6207 }
6208
Willy Tarreauef9a3602012-12-08 22:29:20 +01006209 curproxy->conn_src.source_addr = *sk;
6210 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006211
6212 cur_arg = 2;
6213 while (*(args[cur_arg])) {
6214 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006215#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006216 if (!*args[cur_arg + 1]) {
6217 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6218 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006219 err_code |= ERR_ALERT | ERR_FATAL;
6220 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006221 }
6222
6223 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006224 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6225 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006226 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006227 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6228 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006229 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6230 char *name, *end;
6231
6232 name = args[cur_arg+1] + 7;
6233 while (isspace(*name))
6234 name++;
6235
6236 end = name;
6237 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6238 end++;
6239
Willy Tarreauef9a3602012-12-08 22:29:20 +01006240 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6241 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6242 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6243 curproxy->conn_src.bind_hdr_len = end - name;
6244 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6245 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6246 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006247
6248 /* now look for an occurrence number */
6249 while (isspace(*end))
6250 end++;
6251 if (*end == ',') {
6252 end++;
6253 name = end;
6254 if (*end == '-')
6255 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006256 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006257 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006258 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006259 }
6260
Willy Tarreauef9a3602012-12-08 22:29:20 +01006261 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006262 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6263 " occurrences values smaller than %d.\n",
6264 file, linenum, MAX_HDR_HISTORY);
6265 err_code |= ERR_ALERT | ERR_FATAL;
6266 goto out;
6267 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006268 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006269 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006270
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006271 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006272 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006273 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006274 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006275 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006276 goto out;
6277 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006278
6279 proto = protocol_by_family(sk->ss_family);
6280 if (!proto || !proto->connect) {
6281 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6282 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006283 err_code |= ERR_ALERT | ERR_FATAL;
6284 goto out;
6285 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006286
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006287 if (port1 != port2) {
6288 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6289 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006290 err_code |= ERR_ALERT | ERR_FATAL;
6291 goto out;
6292 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006293 curproxy->conn_src.tproxy_addr = *sk;
6294 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006295 }
6296 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006297#else /* no TPROXY support */
6298 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006299 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006300 err_code |= ERR_ALERT | ERR_FATAL;
6301 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006302#endif
6303 cur_arg += 2;
6304 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006305 }
6306
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006307 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6308#ifdef SO_BINDTODEVICE
6309 if (!*args[cur_arg + 1]) {
6310 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6311 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006312 err_code |= ERR_ALERT | ERR_FATAL;
6313 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006314 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006315 free(curproxy->conn_src.iface_name);
6316 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6317 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006318 global.last_checks |= LSTCHK_NETADM;
6319#else
6320 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6321 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006322 err_code |= ERR_ALERT | ERR_FATAL;
6323 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006324#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006325 cur_arg += 2;
6326 continue;
6327 }
6328 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006329 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006330 err_code |= ERR_ALERT | ERR_FATAL;
6331 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006332 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006333 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006334 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6335 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6336 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006337 err_code |= ERR_ALERT | ERR_FATAL;
6338 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006339 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006340 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006341 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006342 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6343 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006344 err_code |= ERR_ALERT | ERR_FATAL;
6345 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006346 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006347
6348 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006349 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006350 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006351 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006352 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006353 }
6354 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006355 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006356 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006357 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006358 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006359 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006360 }
6361 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006362 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006363 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006364 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006365 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006366 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006367 }
6368 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006369 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006370 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006371 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006372 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006373 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006374 }
6375 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006376 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006377 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006378 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006379 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006380 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006381 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006382 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006383 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006384 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006385 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006386 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006387 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006388 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006389 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006390 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006391 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6392 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006393 err_code |= ERR_ALERT | ERR_FATAL;
6394 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006395 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006396
6397 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006398 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006399 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006400 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006401 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006402 }
6403 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006404 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006405 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006406 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006407 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006408 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006409 }
6410 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006411 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006412 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006413 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006416 }
6417 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006418 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006419 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006420 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006421 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006422 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006423 }
6424 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006425 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006426 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006427 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006428 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006429 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006430 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006431 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006432 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006433 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006434 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006436 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006437 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006438 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006439 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006440
Willy Tarreaubaaee002006-06-26 02:48:02 +02006441 if (curproxy == &defproxy) {
6442 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006443 err_code |= ERR_ALERT | ERR_FATAL;
6444 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006445 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006446 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006447 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448
Willy Tarreaubaaee002006-06-26 02:48:02 +02006449 if (*(args[1]) == 0) {
6450 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006451 err_code |= ERR_ALERT | ERR_FATAL;
6452 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006453 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006454
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006455 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006456 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6457 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6458 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006459 err_code |= ERR_ALERT | ERR_FATAL;
6460 goto out;
6461 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006462 err_code |= warnif_cond_conflicts(cond,
6463 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6464 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006465 }
6466 else if (*args[2]) {
6467 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6468 file, linenum, args[0], args[2]);
6469 err_code |= ERR_ALERT | ERR_FATAL;
6470 goto out;
6471 }
6472
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006473 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006474 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006475 wl->s = strdup(args[1]);
6476 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006477 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006478 }
6479 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006480 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006481 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6482 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 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006486
Willy Tarreauade5ec42010-01-28 19:33:49 +01006487 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006488 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006489 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006490 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006491 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006492 }
6493 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006494 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006495 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006496 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006497 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006498 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006499 }
6500 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006501 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006502 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006503 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006504 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006505 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006506 }
6507 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006508 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006509 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6510 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006511 err_code |= ERR_ALERT | ERR_FATAL;
6512 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006513 }
6514
Willy Tarreauade5ec42010-01-28 19:33:49 +01006515 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006516 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006517 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006518 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006520 }
6521 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006522 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006523 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006524 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006525 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006526 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006527 }
6528 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006529 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006530 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006531 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006532 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006533 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006534 }
6535 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006536 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006537
Willy Tarreaubaaee002006-06-26 02:48:02 +02006538 if (curproxy == &defproxy) {
6539 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006540 err_code |= ERR_ALERT | ERR_FATAL;
6541 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006542 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006543 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006544 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006545
Willy Tarreaubaaee002006-06-26 02:48:02 +02006546 if (*(args[1]) == 0) {
6547 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006548 err_code |= ERR_ALERT | ERR_FATAL;
6549 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006550 }
6551
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006552 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006553 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6554 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6555 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006556 err_code |= ERR_ALERT | ERR_FATAL;
6557 goto out;
6558 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006559 err_code |= warnif_cond_conflicts(cond,
6560 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6561 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006562 }
6563 else if (*args[2]) {
6564 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6565 file, linenum, args[0], args[2]);
6566 err_code |= ERR_ALERT | ERR_FATAL;
6567 goto out;
6568 }
6569
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006570 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006571 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006572 wl->s = strdup(args[1]);
6573 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006574 }
6575 else if (!strcmp(args[0], "errorloc") ||
6576 !strcmp(args[0], "errorloc302") ||
6577 !strcmp(args[0], "errorloc303")) { /* error location */
6578 int errnum, errlen;
6579 char *err;
6580
Willy Tarreau977b8e42006-12-29 14:19:17 +01006581 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006582 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006583
Willy Tarreaubaaee002006-06-26 02:48:02 +02006584 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006585 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006586 err_code |= ERR_ALERT | ERR_FATAL;
6587 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006588 }
6589
6590 errnum = atol(args[1]);
6591 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006592 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6593 err = malloc(errlen);
6594 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006595 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006596 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6597 err = malloc(errlen);
6598 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006599 }
6600
Willy Tarreau0f772532006-12-23 20:51:41 +01006601 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6602 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006603 chunk_destroy(&curproxy->errmsg[rc]);
6604 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006605 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006606 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006607 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006608
6609 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006610 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6611 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006612 free(err);
6613 }
6614 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006615 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6616 int errnum, errlen, fd;
6617 char *err;
6618 struct stat stat;
6619
6620 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006621 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006622
6623 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006624 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006625 err_code |= ERR_ALERT | ERR_FATAL;
6626 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006627 }
6628
6629 fd = open(args[2], O_RDONLY);
6630 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6631 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6632 file, linenum, args[2], args[1]);
6633 if (fd >= 0)
6634 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006635 err_code |= ERR_ALERT | ERR_FATAL;
6636 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006637 }
6638
Willy Tarreau27a674e2009-08-17 07:23:33 +02006639 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006640 errlen = stat.st_size;
6641 } else {
6642 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006643 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006644 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006645 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006646 }
6647
6648 err = malloc(errlen); /* malloc() must succeed during parsing */
6649 errnum = read(fd, err, errlen);
6650 if (errnum != errlen) {
6651 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6652 file, linenum, args[2], args[1]);
6653 close(fd);
6654 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006655 err_code |= ERR_ALERT | ERR_FATAL;
6656 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006657 }
6658 close(fd);
6659
6660 errnum = atol(args[1]);
6661 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6662 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006663 chunk_destroy(&curproxy->errmsg[rc]);
6664 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006665 break;
6666 }
6667 }
6668
6669 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006670 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6671 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006672 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006673 free(err);
6674 }
6675 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006676 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006677 struct cfg_kw_list *kwl;
6678 int index;
6679
6680 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6681 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6682 if (kwl->kw[index].section != CFG_LISTEN)
6683 continue;
6684 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6685 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006686 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006687 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006688 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006689 err_code |= ERR_ALERT | ERR_FATAL;
6690 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006691 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006692 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006693 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006694 err_code |= ERR_WARN;
6695 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006696 }
Willy Tarreau93893792009-07-23 13:19:11 +02006697 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006698 }
6699 }
6700 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006701
Willy Tarreau6daf3432008-01-22 16:44:08 +01006702 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006703 err_code |= ERR_ALERT | ERR_FATAL;
6704 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006705 }
Willy Tarreau93893792009-07-23 13:19:11 +02006706 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006707 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006708 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006709}
6710
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006711int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006712cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6713{
6714#ifdef CONFIG_HAP_NS
6715 const char *err;
6716 const char *item = args[0];
6717
6718 if (!strcmp(item, "namespace_list")) {
6719 return 0;
6720 }
6721 else if (!strcmp(item, "namespace")) {
6722 size_t idx = 1;
6723 const char *current;
6724 while (*(current = args[idx++])) {
6725 err = invalid_char(current);
6726 if (err) {
6727 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6728 file, linenum, *err, item, current);
6729 return ERR_ALERT | ERR_FATAL;
6730 }
6731
6732 if (netns_store_lookup(current, strlen(current))) {
6733 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6734 file, linenum, current);
6735 return ERR_ALERT | ERR_FATAL;
6736 }
6737 if (!netns_store_insert(current)) {
6738 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6739 file, linenum, current);
6740 return ERR_ALERT | ERR_FATAL;
6741 }
6742 }
6743 }
6744
6745 return 0;
6746#else
6747 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6748 file, linenum);
6749 return ERR_ALERT | ERR_FATAL;
6750#endif
6751}
6752
6753int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006754cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6755{
6756
6757 int err_code = 0;
6758 const char *err;
6759
6760 if (!strcmp(args[0], "userlist")) { /* new userlist */
6761 struct userlist *newul;
6762
6763 if (!*args[1]) {
6764 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6765 file, linenum, args[0]);
6766 err_code |= ERR_ALERT | ERR_FATAL;
6767 goto out;
6768 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006769 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6770 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006771
6772 err = invalid_char(args[1]);
6773 if (err) {
6774 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6775 file, linenum, *err, args[0], args[1]);
6776 err_code |= ERR_ALERT | ERR_FATAL;
6777 goto out;
6778 }
6779
6780 for (newul = userlist; newul; newul = newul->next)
6781 if (!strcmp(newul->name, args[1])) {
6782 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6783 file, linenum, args[1]);
6784 err_code |= ERR_WARN;
6785 goto out;
6786 }
6787
Vincent Bernat02779b62016-04-03 13:48:43 +02006788 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006789 if (!newul) {
6790 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6791 err_code |= ERR_ALERT | ERR_ABORT;
6792 goto out;
6793 }
6794
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006795 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006796 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006797 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6798 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006799 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006800 goto out;
6801 }
6802
6803 newul->next = userlist;
6804 userlist = newul;
6805
6806 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006807 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006808 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006809 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006810
6811 if (!*args[1]) {
6812 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6813 file, linenum, args[0]);
6814 err_code |= ERR_ALERT | ERR_FATAL;
6815 goto out;
6816 }
6817
6818 err = invalid_char(args[1]);
6819 if (err) {
6820 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6821 file, linenum, *err, args[0], args[1]);
6822 err_code |= ERR_ALERT | ERR_FATAL;
6823 goto out;
6824 }
6825
William Lallemand4ac9f542015-05-28 18:03:51 +02006826 if (!userlist)
6827 goto out;
6828
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006829 for (ag = userlist->groups; ag; ag = ag->next)
6830 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006831 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6832 file, linenum, args[1], userlist->name);
6833 err_code |= ERR_ALERT;
6834 goto out;
6835 }
6836
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006837 ag = calloc(1, sizeof(*ag));
6838 if (!ag) {
6839 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6840 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006841 goto out;
6842 }
6843
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006844 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006845 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006846 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6847 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006848 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006849 goto out;
6850 }
6851
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006852 cur_arg = 2;
6853
6854 while (*args[cur_arg]) {
6855 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006856 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006857 cur_arg += 2;
6858 continue;
6859 } else {
6860 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6861 file, linenum, args[0]);
6862 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006863 free(ag->groupusers);
6864 free(ag->name);
6865 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006866 goto out;
6867 }
6868 }
6869
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006870 ag->next = userlist->groups;
6871 userlist->groups = ag;
6872
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006873 } else if (!strcmp(args[0], "user")) { /* new user */
6874 struct auth_users *newuser;
6875 int cur_arg;
6876
6877 if (!*args[1]) {
6878 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6879 file, linenum, args[0]);
6880 err_code |= ERR_ALERT | ERR_FATAL;
6881 goto out;
6882 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006883 if (!userlist)
6884 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006885
6886 for (newuser = userlist->users; newuser; newuser = newuser->next)
6887 if (!strcmp(newuser->user, args[1])) {
6888 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6889 file, linenum, args[1], userlist->name);
6890 err_code |= ERR_ALERT;
6891 goto out;
6892 }
6893
Vincent Bernat02779b62016-04-03 13:48:43 +02006894 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006895 if (!newuser) {
6896 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6897 err_code |= ERR_ALERT | ERR_ABORT;
6898 goto out;
6899 }
6900
6901 newuser->user = strdup(args[1]);
6902
6903 newuser->next = userlist->users;
6904 userlist->users = newuser;
6905
6906 cur_arg = 2;
6907
6908 while (*args[cur_arg]) {
6909 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006910#ifdef CONFIG_HAP_CRYPT
6911 if (!crypt("", args[cur_arg + 1])) {
6912 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6913 file, linenum, newuser->user);
6914 err_code |= ERR_ALERT | ERR_FATAL;
6915 goto out;
6916 }
6917#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006918 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6919 file, linenum);
6920 err_code |= ERR_ALERT;
6921#endif
6922 newuser->pass = strdup(args[cur_arg + 1]);
6923 cur_arg += 2;
6924 continue;
6925 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6926 newuser->pass = strdup(args[cur_arg + 1]);
6927 newuser->flags |= AU_O_INSECURE;
6928 cur_arg += 2;
6929 continue;
6930 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006931 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006932 cur_arg += 2;
6933 continue;
6934 } else {
6935 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6936 file, linenum, args[0]);
6937 err_code |= ERR_ALERT | ERR_FATAL;
6938 goto out;
6939 }
6940 }
6941 } else {
6942 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
6943 err_code |= ERR_ALERT | ERR_FATAL;
6944 }
6945
6946out:
6947 return err_code;
6948}
Willy Tarreaubaaee002006-06-26 02:48:02 +02006949
6950/*
6951 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02006952 * Returns the error code, 0 if OK, or any combination of :
6953 * - ERR_ABORT: must abort ASAP
6954 * - ERR_FATAL: we can continue parsing but not start the service
6955 * - ERR_WARN: a warning has been emitted
6956 * - ERR_ALERT: an alert has been emitted
6957 * Only the two first ones can stop processing, the two others are just
6958 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02006959 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02006960int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02006961{
William Lallemand64e84512015-05-12 14:25:37 +02006962 char *thisline;
6963 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006964 FILE *f;
6965 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02006966 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006967 struct cfg_section *cs = NULL;
6968 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02006969 int readbytes = 0;
6970
6971 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02006972 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02006973 return -1;
6974 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01006975
David Carlier97880bb2016-04-08 10:35:26 +01006976 if ((f=fopen(file,"r")) == NULL) {
6977 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006978 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01006979 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006980
William Lallemandb2f07452015-05-12 14:27:13 +02006981next_line:
William Lallemand64e84512015-05-12 14:25:37 +02006982 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02006983 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006984 char *end;
6985 char *args[MAX_LINE_ARGS + 1];
6986 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02006987 int dquote = 0; /* double quote */
6988 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006989
Willy Tarreaubaaee002006-06-26 02:48:02 +02006990 linenum++;
6991
6992 end = line + strlen(line);
6993
William Lallemand64e84512015-05-12 14:25:37 +02006994 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01006995 /* Check if we reached the limit and the last char is not \n.
6996 * Watch out for the last line without the terminating '\n'!
6997 */
William Lallemand64e84512015-05-12 14:25:37 +02006998 char *newline;
6999 int newlinesize = linesize * 2;
7000
7001 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7002 if (newline == NULL) {
7003 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7004 file, linenum);
7005 err_code |= ERR_ALERT | ERR_FATAL;
7006 continue;
7007 }
7008
7009 readbytes = linesize - 1;
7010 linesize = newlinesize;
7011 thisline = newline;
7012 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007013 }
7014
William Lallemand64e84512015-05-12 14:25:37 +02007015 readbytes = 0;
7016
Willy Tarreaubaaee002006-06-26 02:48:02 +02007017 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007018 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007019 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007020
Willy Tarreaubaaee002006-06-26 02:48:02 +02007021 arg = 0;
7022 args[arg] = line;
7023
7024 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007025 if (*line == '"' && !squote) { /* double quote outside single quotes */
7026 if (dquote)
7027 dquote = 0;
7028 else
7029 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007030 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007031 end--;
7032 }
7033 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7034 if (squote)
7035 squote = 0;
7036 else
7037 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007038 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007039 end--;
7040 }
7041 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007042 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7043 * C equivalent value. Other combinations left unchanged (eg: \1).
7044 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007045 int skip = 0;
7046 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7047 *line = line[1];
7048 skip = 1;
7049 }
7050 else if (line[1] == 'r') {
7051 *line = '\r';
7052 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007053 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007054 else if (line[1] == 'n') {
7055 *line = '\n';
7056 skip = 1;
7057 }
7058 else if (line[1] == 't') {
7059 *line = '\t';
7060 skip = 1;
7061 }
7062 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007063 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007064 unsigned char hex1, hex2;
7065 hex1 = toupper(line[2]) - '0';
7066 hex2 = toupper(line[3]) - '0';
7067 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7068 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7069 *line = (hex1<<4) + hex2;
7070 skip = 3;
7071 }
7072 else {
7073 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007074 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007075 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007076 } else if (line[1] == '"') {
7077 *line = '"';
7078 skip = 1;
7079 } else if (line[1] == '\'') {
7080 *line = '\'';
7081 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007082 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7083 *line = '$';
7084 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007085 }
7086 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007087 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007088 end -= skip;
7089 }
7090 line++;
7091 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007092 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007093 /* end of string, end of loop */
7094 *line = 0;
7095 break;
7096 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007097 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007098 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007099 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007100 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 line++;
7102 args[++arg] = line;
7103 }
William Lallemandb2f07452015-05-12 14:27:13 +02007104 else if (dquote && *line == '$') {
7105 /* environment variables are evaluated inside double quotes */
7106 char *var_beg;
7107 char *var_end;
7108 char save_char;
7109 char *value;
7110 int val_len;
7111 int newlinesize;
7112 int braces = 0;
7113
7114 var_beg = line + 1;
7115 var_end = var_beg;
7116
7117 if (*var_beg == '{') {
7118 var_beg++;
7119 var_end++;
7120 braces = 1;
7121 }
7122
7123 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7124 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7125 err_code |= ERR_ALERT | ERR_FATAL;
7126 goto next_line; /* skip current line */
7127 }
7128
7129 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7130 var_end++;
7131
7132 save_char = *var_end;
7133 *var_end = '\0';
7134 value = getenv(var_beg);
7135 *var_end = save_char;
7136 val_len = value ? strlen(value) : 0;
7137
7138 if (braces) {
7139 if (*var_end == '}') {
7140 var_end++;
7141 braces = 0;
7142 } else {
7143 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7144 err_code |= ERR_ALERT | ERR_FATAL;
7145 goto next_line; /* skip current line */
7146 }
7147 }
7148
7149 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7150
7151 /* if not enough space in thisline */
7152 if (newlinesize > linesize) {
7153 char *newline;
7154
7155 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7156 if (newline == NULL) {
7157 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7158 err_code |= ERR_ALERT | ERR_FATAL;
7159 goto next_line; /* slip current line */
7160 }
7161 /* recompute pointers if realloc returns a new pointer */
7162 if (newline != thisline) {
7163 int i;
7164 int diff;
7165
7166 for (i = 0; i <= arg; i++) {
7167 diff = args[i] - thisline;
7168 args[i] = newline + diff;
7169 }
7170
7171 diff = var_end - thisline;
7172 var_end = newline + diff;
7173 diff = end - thisline;
7174 end = newline + diff;
7175 diff = line - thisline;
7176 line = newline + diff;
7177 thisline = newline;
7178 }
7179 linesize = newlinesize;
7180 }
7181
7182 /* insert value inside the line */
7183 memmove(line + val_len, var_end, end - var_end + 1);
7184 memcpy(line, value, val_len);
7185 end += val_len - (var_end - line);
7186 line += val_len;
7187 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007188 else {
7189 line++;
7190 }
7191 }
William Lallemandb2f07452015-05-12 14:27:13 +02007192
William Lallemandf9873ba2015-05-05 17:37:14 +02007193 if (dquote) {
7194 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7195 err_code |= ERR_ALERT | ERR_FATAL;
7196 }
7197
7198 if (squote) {
7199 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7200 err_code |= ERR_ALERT | ERR_FATAL;
7201 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007202
7203 /* empty line */
7204 if (!**args)
7205 continue;
7206
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007207 if (*line) {
7208 /* we had to stop due to too many args.
7209 * Let's terminate the string, print the offending part then cut the
7210 * last arg.
7211 */
7212 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7213 line++;
7214 *line = '\0';
7215
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007216 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007217 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007218 err_code |= ERR_ALERT | ERR_FATAL;
7219 args[arg] = line;
7220 }
7221
Willy Tarreau540abe42007-05-02 20:50:16 +02007222 /* zero out remaining args and ensure that at least one entry
7223 * is zeroed out.
7224 */
7225 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007226 args[arg] = line;
7227 }
7228
Willy Tarreau3842f002009-06-14 11:39:52 +02007229 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007230 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007231 char *tmp;
7232
Willy Tarreau3842f002009-06-14 11:39:52 +02007233 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007234 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007235 for (arg=0; *args[arg+1]; arg++)
7236 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007237 *tmp = '\0'; // fix the next arg to \0
7238 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007239 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007240 else if (!strcmp(args[0], "default")) {
7241 kwm = KWM_DEF;
7242 for (arg=0; *args[arg+1]; arg++)
7243 args[arg] = args[arg+1]; // shift args after inversion
7244 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007245
William Lallemand0f99e342011-10-12 17:50:54 +02007246 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7247 strcmp(args[0], "log") != 0) {
7248 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007249 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007250 }
7251
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007252 /* detect section start */
7253 list_for_each_entry(ics, &sections, list) {
7254 if (strcmp(args[0], ics->section_name) == 0) {
7255 cursection = ics->section_name;
7256 cs = ics;
7257 break;
7258 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007259 }
7260
Willy Tarreaubaaee002006-06-26 02:48:02 +02007261 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007262 if (cs)
7263 err_code |= cs->section_parser(file, linenum, args, kwm);
7264 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007265 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007266 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007267 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007268
7269 if (err_code & ERR_ABORT)
7270 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007271 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007272 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007273 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007274 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007275 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007276}
7277
Willy Tarreau64ab6072014-09-16 12:17:36 +02007278/* This function propagates processes from frontend <from> to backend <to> so
7279 * that it is always guaranteed that a backend pointed to by a frontend is
7280 * bound to all of its processes. After that, if the target is a "listen"
7281 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007282 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007283 * checked first to ensure that <to> is already bound to all processes of
7284 * <from>, there is no risk of looping and we ensure to follow the shortest
7285 * path to the destination.
7286 *
7287 * It is possible to set <to> to NULL for the first call so that the function
7288 * takes care of visiting the initial frontend in <from>.
7289 *
7290 * It is important to note that the function relies on the fact that all names
7291 * have already been resolved.
7292 */
7293void propagate_processes(struct proxy *from, struct proxy *to)
7294{
7295 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007296
7297 if (to) {
7298 /* check whether we need to go down */
7299 if (from->bind_proc &&
7300 (from->bind_proc & to->bind_proc) == from->bind_proc)
7301 return;
7302
7303 if (!from->bind_proc && !to->bind_proc)
7304 return;
7305
7306 to->bind_proc = from->bind_proc ?
7307 (to->bind_proc | from->bind_proc) : 0;
7308
7309 /* now propagate down */
7310 from = to;
7311 }
7312
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007313 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007314 return;
7315
Willy Tarreauf6b70012014-12-18 14:00:43 +01007316 if (from->state == PR_STSTOPPED)
7317 return;
7318
Willy Tarreau64ab6072014-09-16 12:17:36 +02007319 /* default_backend */
7320 if (from->defbe.be)
7321 propagate_processes(from, from->defbe.be);
7322
7323 /* use_backend */
7324 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007325 if (rule->dynamic)
7326 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007327 to = rule->be.backend;
7328 propagate_processes(from, to);
7329 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007330}
7331
Willy Tarreaubb925012009-07-23 13:36:36 +02007332/*
7333 * Returns the error code, 0 if OK, or any combination of :
7334 * - ERR_ABORT: must abort ASAP
7335 * - ERR_FATAL: we can continue parsing but not start the service
7336 * - ERR_WARN: a warning has been emitted
7337 * - ERR_ALERT: an alert has been emitted
7338 * Only the two first ones can stop processing, the two others are just
7339 * indicators.
7340 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007341int check_config_validity()
7342{
7343 int cfgerr = 0;
7344 struct proxy *curproxy = NULL;
7345 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007346 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007347 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007348 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007349
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007350 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007351 /*
7352 * Now, check for the integrity of all that we have collected.
7353 */
7354
7355 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007356 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007357
Willy Tarreau193b8c62012-11-22 00:17:38 +01007358 if (!global.tune.max_http_hdr)
7359 global.tune.max_http_hdr = MAX_HTTP_HDR;
7360
7361 if (!global.tune.cookie_len)
7362 global.tune.cookie_len = CAPTURE_LEN;
7363
7364 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7365
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007366 /* Post initialisation of the users and groups lists. */
7367 err_code = userlist_postinit();
7368 if (err_code != ERR_NONE)
7369 goto out;
7370
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007371 /* first, we will invert the proxy list order */
7372 curproxy = NULL;
7373 while (proxy) {
7374 struct proxy *next;
7375
7376 next = proxy->next;
7377 proxy->next = curproxy;
7378 curproxy = proxy;
7379 if (!next)
7380 break;
7381 proxy = next;
7382 }
7383
Willy Tarreau419ead82014-09-16 13:41:21 +02007384 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007385 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007386 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007387 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007388 struct act_rule *trule;
7389 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007390 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007391 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007392 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007393
Willy Tarreau050536d2012-10-04 08:47:34 +02007394 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007395 /* proxy ID not set, use automatic numbering with first
7396 * spare entry starting with next_pxid.
7397 */
7398 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7399 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7400 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007401 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007402 next_pxid++;
7403
Willy Tarreau55ea7572007-06-17 19:56:27 +02007404
Willy Tarreaubaaee002006-06-26 02:48:02 +02007405 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007406 /* ensure we don't keep listeners uselessly bound */
7407 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007408 free((void *)curproxy->table.peers.name);
7409 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007410 continue;
7411 }
7412
Willy Tarreau102df612014-05-07 23:56:38 +02007413 /* Check multi-process mode compatibility for the current proxy */
7414
7415 if (curproxy->bind_proc) {
7416 /* an explicit bind-process was specified, let's check how many
7417 * processes remain.
7418 */
David Carliere6c39412015-07-02 07:00:17 +00007419 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007420
7421 curproxy->bind_proc &= nbits(global.nbproc);
7422 if (!curproxy->bind_proc && nbproc == 1) {
7423 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);
7424 curproxy->bind_proc = 1;
7425 }
7426 else if (!curproxy->bind_proc && nbproc > 1) {
7427 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);
7428 curproxy->bind_proc = 0;
7429 }
7430 }
7431
Willy Tarreau3d209582014-05-09 17:06:11 +02007432 /* check and reduce the bind-proc of each listener */
7433 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7434 unsigned long mask;
7435
7436 if (!bind_conf->bind_proc)
7437 continue;
7438
7439 mask = nbits(global.nbproc);
7440 if (curproxy->bind_proc)
7441 mask &= curproxy->bind_proc;
7442 /* mask cannot be null here thanks to the previous checks */
7443
David Carliere6c39412015-07-02 07:00:17 +00007444 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007445 bind_conf->bind_proc &= mask;
7446
7447 if (!bind_conf->bind_proc && nbproc == 1) {
7448 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",
7449 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7450 bind_conf->bind_proc = mask & ~(mask - 1);
7451 }
7452 else if (!bind_conf->bind_proc && nbproc > 1) {
7453 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",
7454 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7455 bind_conf->bind_proc = 0;
7456 }
7457 }
7458
Willy Tarreauff01a212009-03-15 13:46:16 +01007459 switch (curproxy->mode) {
7460 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007461 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007462 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007463 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7464 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007465 cfgerr++;
7466 }
7467
7468 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007469 Warning("config : servers will be ignored for %s '%s'.\n",
7470 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007471 break;
7472
7473 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007474 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007475 break;
7476
7477 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007478 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007479 break;
7480 }
7481
Willy Tarreauf3934b82015-08-11 11:36:45 +02007482 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7483 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7484 proxy_type_str(curproxy), curproxy->id);
7485 err_code |= ERR_WARN;
7486 }
7487
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007488 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007489 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007490 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007491 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7492 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007493 cfgerr++;
7494 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007495#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007496 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007497 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7498 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007499 cfgerr++;
7500 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007501#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007502 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007503 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7504 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007505 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007506 }
7507 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007508 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007509 /* If no LB algo is set in a backend, and we're not in
7510 * transparent mode, dispatch mode nor proxy mode, we
7511 * want to use balance roundrobin by default.
7512 */
7513 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7514 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007515 }
7516 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007517
Willy Tarreau1620ec32011-08-06 17:05:02 +02007518 if (curproxy->options & PR_O_DISPATCH)
7519 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7520 else if (curproxy->options & PR_O_HTTP_PROXY)
7521 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7522 else if (curproxy->options & PR_O_TRANSP)
7523 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007524
Willy Tarreau1620ec32011-08-06 17:05:02 +02007525 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7526 if (curproxy->options & PR_O_DISABLE404) {
7527 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7528 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7529 err_code |= ERR_WARN;
7530 curproxy->options &= ~PR_O_DISABLE404;
7531 }
7532 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7533 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7534 "send-state", proxy_type_str(curproxy), curproxy->id);
7535 err_code |= ERR_WARN;
7536 curproxy->options &= ~PR_O2_CHK_SNDST;
7537 }
Willy Tarreauef781042010-01-27 11:53:01 +01007538 }
7539
Simon Horman98637e52014-06-20 12:30:16 +09007540 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7541 if (!global.external_check) {
7542 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7543 curproxy->id, "option external-check");
7544 cfgerr++;
7545 }
7546 if (!curproxy->check_command) {
7547 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7548 curproxy->id, "option external-check");
7549 cfgerr++;
7550 }
7551 }
7552
Simon Horman64e34162015-02-06 11:11:57 +09007553 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007554 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7555 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007556 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7557 "'email-alert myhostname', or 'email-alert to' "
7558 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007559 "to be present).\n",
7560 proxy_type_str(curproxy), curproxy->id);
7561 err_code |= ERR_WARN;
7562 free_email_alert(curproxy);
7563 }
7564 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007565 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007566 }
7567
Simon Horman98637e52014-06-20 12:30:16 +09007568 if (curproxy->check_command) {
7569 int clear = 0;
7570 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7571 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7572 "external-check command", proxy_type_str(curproxy), curproxy->id);
7573 err_code |= ERR_WARN;
7574 clear = 1;
7575 }
7576 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007577 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007578 curproxy->id, "external-check command");
7579 cfgerr++;
7580 }
7581 if (clear) {
7582 free(curproxy->check_command);
7583 curproxy->check_command = NULL;
7584 }
7585 }
7586
7587 if (curproxy->check_path) {
7588 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7589 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7590 "external-check path", proxy_type_str(curproxy), curproxy->id);
7591 err_code |= ERR_WARN;
7592 free(curproxy->check_path);
7593 curproxy->check_path = NULL;
7594 }
7595 }
7596
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007597 /* if a default backend was specified, let's find it */
7598 if (curproxy->defbe.name) {
7599 struct proxy *target;
7600
Willy Tarreauafb39922015-05-26 12:04:09 +02007601 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007602 if (!target) {
7603 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7604 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007605 cfgerr++;
7606 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007607 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7608 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007609 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007610 } else if (target->mode != curproxy->mode &&
7611 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7612
7613 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7614 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7615 curproxy->conf.file, curproxy->conf.line,
7616 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7617 target->conf.file, target->conf.line);
7618 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007619 } else {
7620 free(curproxy->defbe.name);
7621 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007622
7623 /* Emit a warning if this proxy also has some servers */
7624 if (curproxy->srv) {
7625 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7626 curproxy->id);
7627 err_code |= ERR_WARN;
7628 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007629 }
7630 }
7631
Willy Tarreau55ea7572007-06-17 19:56:27 +02007632 /* find the target proxy for 'use_backend' rules */
7633 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007634 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007635 struct logformat_node *node;
7636 char *pxname;
7637
7638 /* Try to parse the string as a log format expression. If the result
7639 * of the parsing is only one entry containing a simple string, then
7640 * it's a standard string corresponding to a static rule, thus the
7641 * parsing is cancelled and be.name is restored to be resolved.
7642 */
7643 pxname = rule->be.name;
7644 LIST_INIT(&rule->be.expr);
7645 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7646 curproxy->conf.args.file, curproxy->conf.args.line);
7647 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7648
7649 if (!LIST_ISEMPTY(&rule->be.expr)) {
7650 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7651 rule->dynamic = 1;
7652 free(pxname);
7653 continue;
7654 }
7655 /* simple string: free the expression and fall back to static rule */
7656 free(node->arg);
7657 free(node);
7658 }
7659
7660 rule->dynamic = 0;
7661 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007662
Willy Tarreauafb39922015-05-26 12:04:09 +02007663 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007664 if (!target) {
7665 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7666 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007667 cfgerr++;
7668 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007669 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7670 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007671 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007672 } else if (target->mode != curproxy->mode &&
7673 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7674
7675 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7676 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7677 curproxy->conf.file, curproxy->conf.line,
7678 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7679 target->conf.file, target->conf.line);
7680 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007681 } else {
7682 free((void *)rule->be.name);
7683 rule->be.backend = target;
7684 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007685 }
7686
Willy Tarreau64ab6072014-09-16 12:17:36 +02007687 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007688 list_for_each_entry(srule, &curproxy->server_rules, list) {
7689 struct server *target = findserver(curproxy, srule->srv.name);
7690
7691 if (!target) {
7692 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7693 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7694 cfgerr++;
7695 continue;
7696 }
7697 free((void *)srule->srv.name);
7698 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007699 }
7700
Emeric Brunb982a3d2010-01-04 15:45:53 +01007701 /* find the target table for 'stick' rules */
7702 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7703 struct proxy *target;
7704
Emeric Brun1d33b292010-01-04 15:47:17 +01007705 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7706 if (mrule->flags & STK_IS_STORE)
7707 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7708
Emeric Brunb982a3d2010-01-04 15:45:53 +01007709 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007710 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007711 else
7712 target = curproxy;
7713
7714 if (!target) {
7715 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7716 curproxy->id, mrule->table.name);
7717 cfgerr++;
7718 }
7719 else if (target->table.size == 0) {
7720 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7721 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7722 cfgerr++;
7723 }
Willy Tarreau12785782012-04-27 21:37:17 +02007724 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7725 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007726 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7727 cfgerr++;
7728 }
7729 else {
7730 free((void *)mrule->table.name);
7731 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007732 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007733 }
7734 }
7735
7736 /* find the target table for 'store response' rules */
7737 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7738 struct proxy *target;
7739
Emeric Brun1d33b292010-01-04 15:47:17 +01007740 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7741
Emeric Brunb982a3d2010-01-04 15:45:53 +01007742 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007743 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007744 else
7745 target = curproxy;
7746
7747 if (!target) {
7748 Alert("Proxy '%s': unable to find store table '%s'.\n",
7749 curproxy->id, mrule->table.name);
7750 cfgerr++;
7751 }
7752 else if (target->table.size == 0) {
7753 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7754 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7755 cfgerr++;
7756 }
Willy Tarreau12785782012-04-27 21:37:17 +02007757 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7758 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007759 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7760 cfgerr++;
7761 }
7762 else {
7763 free((void *)mrule->table.name);
7764 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007765 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007766 }
7767 }
7768
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007769 /* find the target table for 'tcp-request' layer 4 rules */
7770 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7771 struct proxy *target;
7772
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007773 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007774 continue;
7775
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007776 if (trule->arg.trk_ctr.table.n)
7777 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007778 else
7779 target = curproxy;
7780
7781 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007782 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007783 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007784 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007785 cfgerr++;
7786 }
7787 else if (target->table.size == 0) {
7788 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007789 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007790 cfgerr++;
7791 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007792 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007793 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007794 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007795 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007796 cfgerr++;
7797 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007798 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007799 free(trule->arg.trk_ctr.table.n);
7800 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007801 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007802 * to pass a list of counters to track and allocate them right here using
7803 * stktable_alloc_data_type().
7804 */
7805 }
7806 }
7807
Willy Tarreaud1f96522010-08-03 19:34:32 +02007808 /* find the target table for 'tcp-request' layer 6 rules */
7809 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7810 struct proxy *target;
7811
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007812 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007813 continue;
7814
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007815 if (trule->arg.trk_ctr.table.n)
7816 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007817 else
7818 target = curproxy;
7819
7820 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007821 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007822 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007823 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007824 cfgerr++;
7825 }
7826 else if (target->table.size == 0) {
7827 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007828 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007829 cfgerr++;
7830 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007831 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007832 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007833 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007834 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007835 cfgerr++;
7836 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007837 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007838 free(trule->arg.trk_ctr.table.n);
7839 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007840 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007841 * to pass a list of counters to track and allocate them right here using
7842 * stktable_alloc_data_type().
7843 */
7844 }
7845 }
7846
Baptiste Assmanne9544932015-11-03 23:31:35 +01007847 /* parse http-request capture rules to ensure id really exists */
7848 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7849 if (hrqrule->action != ACT_CUSTOM ||
7850 hrqrule->action_ptr != http_action_req_capture_by_id)
7851 continue;
7852
7853 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7854 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7855 curproxy->id, hrqrule->arg.capid.idx);
7856 cfgerr++;
7857 }
7858 }
7859
7860 /* parse http-response capture rules to ensure id really exists */
7861 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7862 if (hrqrule->action != ACT_CUSTOM ||
7863 hrqrule->action_ptr != http_action_res_capture_by_id)
7864 continue;
7865
7866 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7867 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7868 curproxy->id, hrqrule->arg.capid.idx);
7869 cfgerr++;
7870 }
7871 }
7872
Willy Tarreau09448f72014-06-25 18:12:15 +02007873 /* find the target table for 'http-request' layer 7 rules */
7874 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7875 struct proxy *target;
7876
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007877 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007878 continue;
7879
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007880 if (hrqrule->arg.trk_ctr.table.n)
7881 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007882 else
7883 target = curproxy;
7884
7885 if (!target) {
7886 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007887 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007888 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007889 cfgerr++;
7890 }
7891 else if (target->table.size == 0) {
7892 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007893 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007894 cfgerr++;
7895 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007896 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007897 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007898 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007899 http_trk_idx(hrqrule->action));
7900 cfgerr++;
7901 }
7902 else {
7903 free(hrqrule->arg.trk_ctr.table.n);
7904 hrqrule->arg.trk_ctr.table.t = &target->table;
7905 /* Note: if we decide to enhance the track-sc syntax, we may be able
7906 * to pass a list of counters to track and allocate them right here using
7907 * stktable_alloc_data_type().
7908 */
7909 }
7910 }
7911
7912 /* find the target table for 'http-response' layer 7 rules */
7913 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7914 struct proxy *target;
7915
7916 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
7917 continue;
7918
7919 if (hrqrule->arg.trk_ctr.table.n)
7920 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
7921 else
7922 target = curproxy;
7923
7924 if (!target) {
7925 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7926 curproxy->id, hrqrule->arg.trk_ctr.table.n,
7927 http_trk_idx(hrqrule->action));
7928 cfgerr++;
7929 }
7930 else if (target->table.size == 0) {
7931 Alert("Proxy '%s': table '%s' used but not configured.\n",
7932 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
7933 cfgerr++;
7934 }
7935 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
7936 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7937 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
7938 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007939 cfgerr++;
7940 }
7941 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007942 free(hrqrule->arg.trk_ctr.table.n);
7943 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02007944 /* Note: if we decide to enhance the track-sc syntax, we may be able
7945 * to pass a list of counters to track and allocate them right here using
7946 * stktable_alloc_data_type().
7947 */
7948 }
7949 }
7950
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02007951 /* move any "block" rules at the beginning of the http-request rules */
7952 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
7953 /* insert block_rules into http_req_rules at the beginning */
7954 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
7955 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
7956 curproxy->block_rules.n->p = &curproxy->http_req_rules;
7957 curproxy->http_req_rules.n = curproxy->block_rules.n;
7958 LIST_INIT(&curproxy->block_rules);
7959 }
7960
Emeric Brun32da3c42010-09-23 18:39:19 +02007961 if (curproxy->table.peers.name) {
7962 struct peers *curpeers = peers;
7963
7964 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
7965 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
7966 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01007967 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02007968 break;
7969 }
7970 }
7971
7972 if (!curpeers) {
7973 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
7974 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007975 free((void *)curproxy->table.peers.name);
7976 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007977 cfgerr++;
7978 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02007979 else if (curpeers->state == PR_STSTOPPED) {
7980 /* silently disable this peers section */
7981 curproxy->table.peers.p = NULL;
7982 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007983 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02007984 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
7985 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02007986 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02007987 cfgerr++;
7988 }
7989 }
7990
Simon Horman9dc49962015-01-30 11:22:59 +09007991
7992 if (curproxy->email_alert.mailers.name) {
7993 struct mailers *curmailers = mailers;
7994
7995 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
7996 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
7997 free(curproxy->email_alert.mailers.name);
7998 curproxy->email_alert.mailers.m = curmailers;
7999 curmailers->users++;
8000 break;
8001 }
8002 }
8003
8004 if (!curmailers) {
8005 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8006 curproxy->id, curproxy->email_alert.mailers.name);
8007 free_email_alert(curproxy);
8008 cfgerr++;
8009 }
8010 }
8011
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008012 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008013 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008014 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8015 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8016 "proxy", curproxy->id);
8017 cfgerr++;
8018 goto out_uri_auth_compat;
8019 }
8020
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008021 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008022 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008023 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008024 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008025
Willy Tarreau95fa4692010-02-01 13:05:50 +01008026 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8027 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008028
8029 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008030 uri_auth_compat_req[i++] = "realm";
8031 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8032 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008033
Willy Tarreau95fa4692010-02-01 13:05:50 +01008034 uri_auth_compat_req[i++] = "unless";
8035 uri_auth_compat_req[i++] = "{";
8036 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8037 uri_auth_compat_req[i++] = "}";
8038 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008039
Willy Tarreauff011f22011-01-06 17:51:27 +01008040 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8041 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008042 cfgerr++;
8043 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008044 }
8045
Willy Tarreauff011f22011-01-06 17:51:27 +01008046 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008047
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008048 if (curproxy->uri_auth->auth_realm) {
8049 free(curproxy->uri_auth->auth_realm);
8050 curproxy->uri_auth->auth_realm = NULL;
8051 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008052
8053 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008054 }
8055out_uri_auth_compat:
8056
Dragan Dosen43885c72015-10-01 13:18:13 +02008057 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008058 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008059 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8060 if (!curproxy->conf.logformat_sd_string) {
8061 /* set the default logformat_sd_string */
8062 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8063 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008064 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008065 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008066 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008067
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008068 /* compile the log format */
8069 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008070 if (curproxy->conf.logformat_string != default_http_log_format &&
8071 curproxy->conf.logformat_string != default_tcp_log_format &&
8072 curproxy->conf.logformat_string != clf_http_log_format)
8073 free(curproxy->conf.logformat_string);
8074 curproxy->conf.logformat_string = NULL;
8075 free(curproxy->conf.lfs_file);
8076 curproxy->conf.lfs_file = NULL;
8077 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008078
8079 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8080 free(curproxy->conf.logformat_sd_string);
8081 curproxy->conf.logformat_sd_string = NULL;
8082 free(curproxy->conf.lfsd_file);
8083 curproxy->conf.lfsd_file = NULL;
8084 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008085 }
8086
Willy Tarreau62a61232013-04-12 18:13:46 +02008087 if (curproxy->conf.logformat_string) {
8088 curproxy->conf.args.ctx = ARGC_LOG;
8089 curproxy->conf.args.file = curproxy->conf.lfs_file;
8090 curproxy->conf.args.line = curproxy->conf.lfs_line;
8091 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008092 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008093 curproxy->conf.args.file = NULL;
8094 curproxy->conf.args.line = 0;
8095 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008096
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008097 if (curproxy->conf.logformat_sd_string) {
8098 curproxy->conf.args.ctx = ARGC_LOGSD;
8099 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8100 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8101 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8102 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8103 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8104 curproxy->conf.args.file = NULL;
8105 curproxy->conf.args.line = 0;
8106 }
8107
Willy Tarreau62a61232013-04-12 18:13:46 +02008108 if (curproxy->conf.uniqueid_format_string) {
8109 curproxy->conf.args.ctx = ARGC_UIF;
8110 curproxy->conf.args.file = curproxy->conf.uif_file;
8111 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008112 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008113 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008114 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008115 curproxy->conf.args.file = NULL;
8116 curproxy->conf.args.line = 0;
8117 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008118
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008119 /* only now we can check if some args remain unresolved.
8120 * This must be done after the users and groups resolution.
8121 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008122 cfgerr += smp_resolve_args(curproxy);
8123 if (!cfgerr)
8124 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008125
Willy Tarreau2738a142006-07-08 17:28:09 +02008126 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008127 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008128 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008129 (!curproxy->timeout.connect ||
8130 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008131 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008132 " | While not properly invalid, you will certainly encounter various problems\n"
8133 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008134 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008135 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008136 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008137 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008138
Willy Tarreau1fa31262007-12-03 00:36:16 +01008139 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8140 * We must still support older configurations, so let's find out whether those
8141 * parameters have been set or must be copied from contimeouts.
8142 */
8143 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008144 if (!curproxy->timeout.tarpit ||
8145 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008146 /* tarpit timeout not set. We search in the following order:
8147 * default.tarpit, curr.connect, default.connect.
8148 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008149 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008150 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008151 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008152 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008153 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008154 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008155 }
8156 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008157 (!curproxy->timeout.queue ||
8158 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008159 /* queue timeout not set. We search in the following order:
8160 * default.queue, curr.connect, default.connect.
8161 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008162 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008163 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008164 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008165 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008166 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008167 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008168 }
8169 }
8170
Willy Tarreau1620ec32011-08-06 17:05:02 +02008171 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008172 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008173 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008174 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008175 }
8176
Willy Tarreau215663d2014-06-13 18:30:23 +02008177 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8178 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8179 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8180 proxy_type_str(curproxy), curproxy->id);
8181 err_code |= ERR_WARN;
8182 }
8183
Willy Tarreau193b8c62012-11-22 00:17:38 +01008184 /* ensure that cookie capture length is not too large */
8185 if (curproxy->capture_len >= global.tune.cookie_len) {
8186 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8187 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8188 err_code |= ERR_WARN;
8189 curproxy->capture_len = global.tune.cookie_len - 1;
8190 }
8191
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008192 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008193 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008194 curproxy->req_cap_pool = create_pool("ptrcap",
8195 curproxy->nb_req_cap * sizeof(char *),
8196 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008197 }
8198
8199 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008200 curproxy->rsp_cap_pool = create_pool("ptrcap",
8201 curproxy->nb_rsp_cap * sizeof(char *),
8202 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008203 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008204
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008205 switch (curproxy->load_server_state_from_file) {
8206 case PR_SRV_STATE_FILE_UNSPEC:
8207 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8208 break;
8209 case PR_SRV_STATE_FILE_GLOBAL:
8210 if (!global.server_state_file) {
8211 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",
8212 curproxy->id);
8213 err_code |= ERR_WARN;
8214 }
8215 break;
8216 }
8217
Willy Tarreaubaaee002006-06-26 02:48:02 +02008218 /* first, we will invert the servers list order */
8219 newsrv = NULL;
8220 while (curproxy->srv) {
8221 struct server *next;
8222
8223 next = curproxy->srv->next;
8224 curproxy->srv->next = newsrv;
8225 newsrv = curproxy->srv;
8226 if (!next)
8227 break;
8228 curproxy->srv = next;
8229 }
8230
Willy Tarreau17edc812014-01-03 12:14:34 +01008231 /* Check that no server name conflicts. This causes trouble in the stats.
8232 * We only emit a warning for the first conflict affecting each server,
8233 * in order to avoid combinatory explosion if all servers have the same
8234 * name. We do that only for servers which do not have an explicit ID,
8235 * because these IDs were made also for distinguishing them and we don't
8236 * want to annoy people who correctly manage them.
8237 */
8238 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8239 struct server *other_srv;
8240
8241 if (newsrv->puid)
8242 continue;
8243
8244 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8245 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8246 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8247 newsrv->conf.file, newsrv->conf.line,
8248 proxy_type_str(curproxy), curproxy->id,
8249 newsrv->id, other_srv->conf.line);
8250 break;
8251 }
8252 }
8253 }
8254
Willy Tarreaudd701652010-05-25 23:03:02 +02008255 /* assign automatic UIDs to servers which don't have one yet */
8256 next_id = 1;
8257 newsrv = curproxy->srv;
8258 while (newsrv != NULL) {
8259 if (!newsrv->puid) {
8260 /* server ID not set, use automatic numbering with first
8261 * spare entry starting with next_svid.
8262 */
8263 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8264 newsrv->conf.id.key = newsrv->puid = next_id;
8265 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8266 }
8267 next_id++;
8268 newsrv = newsrv->next;
8269 }
8270
Willy Tarreau20697042007-11-15 23:26:18 +01008271 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008272 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008273
Willy Tarreau62c3be22012-01-20 13:12:32 +01008274 /*
8275 * If this server supports a maxconn parameter, it needs a dedicated
8276 * tasks to fill the emptied slots when a connection leaves.
8277 * Also, resolve deferred tracking dependency if needed.
8278 */
8279 newsrv = curproxy->srv;
8280 while (newsrv != NULL) {
8281 if (newsrv->minconn > newsrv->maxconn) {
8282 /* Only 'minconn' was specified, or it was higher than or equal
8283 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8284 * this will avoid further useless expensive computations.
8285 */
8286 newsrv->maxconn = newsrv->minconn;
8287 } else if (newsrv->maxconn && !newsrv->minconn) {
8288 /* minconn was not specified, so we set it to maxconn */
8289 newsrv->minconn = newsrv->maxconn;
8290 }
8291
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008292#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008293 if (newsrv->use_ssl || newsrv->check.use_ssl)
8294 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008295#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008296
Willy Tarreau2f075e92013-12-03 11:11:34 +01008297 /* set the check type on the server */
8298 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8299
Willy Tarreau62c3be22012-01-20 13:12:32 +01008300 if (newsrv->trackit) {
8301 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008302 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008303 char *pname, *sname;
8304
8305 pname = newsrv->trackit;
8306 sname = strrchr(pname, '/');
8307
8308 if (sname)
8309 *sname++ = '\0';
8310 else {
8311 sname = pname;
8312 pname = NULL;
8313 }
8314
8315 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008316 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008317 if (!px) {
8318 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8319 proxy_type_str(curproxy), curproxy->id,
8320 newsrv->id, pname);
8321 cfgerr++;
8322 goto next_srv;
8323 }
8324 } else
8325 px = curproxy;
8326
8327 srv = findserver(px, sname);
8328 if (!srv) {
8329 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8330 proxy_type_str(curproxy), curproxy->id,
8331 newsrv->id, sname);
8332 cfgerr++;
8333 goto next_srv;
8334 }
8335
Willy Tarreau32091232014-05-16 13:52:00 +02008336 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8337 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8338 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008339 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008340 "tracking as it does not have any check nor agent enabled.\n",
8341 proxy_type_str(curproxy), curproxy->id,
8342 newsrv->id, px->id, srv->id);
8343 cfgerr++;
8344 goto next_srv;
8345 }
8346
8347 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8348
8349 if (loop) {
8350 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8351 "belongs to a tracking chain looping back to %s/%s.\n",
8352 proxy_type_str(curproxy), curproxy->id,
8353 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008354 cfgerr++;
8355 goto next_srv;
8356 }
8357
8358 if (curproxy != px &&
8359 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8360 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8361 "tracking: disable-on-404 option inconsistency.\n",
8362 proxy_type_str(curproxy), curproxy->id,
8363 newsrv->id, px->id, srv->id);
8364 cfgerr++;
8365 goto next_srv;
8366 }
8367
8368 /* if the other server is forced disabled, we have to do the same here */
Willy Tarreau20125212014-05-13 19:44:56 +02008369 if (srv->admin & SRV_ADMF_MAINT) {
Willy Tarreaua0066dd2014-05-16 11:25:16 +02008370 newsrv->admin |= SRV_ADMF_IMAINT;
Willy Tarreau892337c2014-05-13 23:41:20 +02008371 newsrv->state = SRV_ST_STOPPED;
Simon Horman125d0992013-02-24 17:23:38 +09008372 newsrv->check.health = 0;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008373 }
8374
8375 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008376 newsrv->tracknext = srv->trackers;
8377 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008378
8379 free(newsrv->trackit);
8380 newsrv->trackit = NULL;
8381 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008382
8383 /*
8384 * resolve server's resolvers name and update the resolvers pointer
8385 * accordingly
8386 */
8387 if (newsrv->resolvers_id) {
8388 struct dns_resolvers *curr_resolvers;
8389 int found;
8390
8391 found = 0;
8392 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8393 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8394 found = 1;
8395 break;
8396 }
8397 }
8398
8399 if (!found) {
8400 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8401 proxy_type_str(curproxy), curproxy->id,
8402 newsrv->id, newsrv->resolvers_id);
8403 cfgerr++;
8404 } else {
8405 free(newsrv->resolvers_id);
8406 newsrv->resolvers_id = NULL;
8407 if (newsrv->resolution)
8408 newsrv->resolution->resolvers = curr_resolvers;
8409 }
8410 }
8411 else {
8412 /* if no resolvers section associated to this server
8413 * we can clean up the associated resolution structure
8414 */
8415 if (newsrv->resolution) {
8416 free(newsrv->resolution->hostname_dn);
8417 newsrv->resolution->hostname_dn = NULL;
8418 free(newsrv->resolution);
8419 newsrv->resolution = NULL;
8420 }
8421 }
8422
Willy Tarreau62c3be22012-01-20 13:12:32 +01008423 next_srv:
8424 newsrv = newsrv->next;
8425 }
8426
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008427 /* We have to initialize the server lookup mechanism depending
8428 * on what LB algorithm was choosen.
8429 */
8430
8431 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8432 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8433 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008434 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8435 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8436 init_server_map(curproxy);
8437 } else {
8438 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8439 fwrr_init_server_groups(curproxy);
8440 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008441 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008442
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008443 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008444 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8445 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8446 fwlc_init_server_tree(curproxy);
8447 } else {
8448 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8449 fas_init_server_tree(curproxy);
8450 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008451 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008452
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008453 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008454 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8455 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8456 chash_init_server_tree(curproxy);
8457 } else {
8458 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8459 init_server_map(curproxy);
8460 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008461 break;
8462 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008463
8464 if (curproxy->options & PR_O_LOGASAP)
8465 curproxy->to_log &= ~LW_BYTES;
8466
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008467 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008468 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8469 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008470 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8471 proxy_type_str(curproxy), curproxy->id);
8472 err_code |= ERR_WARN;
8473 }
8474
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008475 if (curproxy->mode != PR_MODE_HTTP) {
8476 int optnum;
8477
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008478 if (curproxy->uri_auth) {
8479 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8480 proxy_type_str(curproxy), curproxy->id);
8481 err_code |= ERR_WARN;
8482 curproxy->uri_auth = NULL;
8483 }
8484
Willy Tarreau87cf5142011-08-19 22:57:24 +02008485 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008486 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8487 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8488 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008489 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008490 }
8491
8492 if (curproxy->options & PR_O_ORGTO) {
8493 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8494 "originalto", proxy_type_str(curproxy), curproxy->id);
8495 err_code |= ERR_WARN;
8496 curproxy->options &= ~PR_O_ORGTO;
8497 }
8498
8499 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8500 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8501 (curproxy->cap & cfg_opts[optnum].cap) &&
8502 (curproxy->options & cfg_opts[optnum].val)) {
8503 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8504 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8505 err_code |= ERR_WARN;
8506 curproxy->options &= ~cfg_opts[optnum].val;
8507 }
8508 }
8509
8510 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8511 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8512 (curproxy->cap & cfg_opts2[optnum].cap) &&
8513 (curproxy->options2 & cfg_opts2[optnum].val)) {
8514 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8515 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8516 err_code |= ERR_WARN;
8517 curproxy->options2 &= ~cfg_opts2[optnum].val;
8518 }
8519 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008520
Willy Tarreau29fbe512015-08-20 19:35:14 +02008521#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008522 if (curproxy->conn_src.bind_hdr_occ) {
8523 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008524 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008525 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008526 err_code |= ERR_WARN;
8527 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008528#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008529 }
8530
Willy Tarreaubaaee002006-06-26 02:48:02 +02008531 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008532 * ensure that we're not cross-dressing a TCP server into HTTP.
8533 */
8534 newsrv = curproxy->srv;
8535 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008536 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008537 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8538 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008539 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008540 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008541
Willy Tarreau0cec3312011-10-31 13:49:26 +01008542 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8543 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8544 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8545 err_code |= ERR_WARN;
8546 }
8547
Willy Tarreauc93cd162014-05-13 15:54:22 +02008548 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008549 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8550 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8551 err_code |= ERR_WARN;
8552 }
8553
Willy Tarreau29fbe512015-08-20 19:35:14 +02008554#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008555 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8556 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008557 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 +01008558 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008559 err_code |= ERR_WARN;
8560 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008561#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008562 newsrv = newsrv->next;
8563 }
8564
Willy Tarreaue42bd962014-09-16 16:21:19 +02008565 /* check if we have a frontend with "tcp-request content" looking at L7
8566 * with no inspect-delay
8567 */
8568 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8569 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008570 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008571 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008572 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008573 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008574 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008575 break;
8576 }
8577
8578 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8579 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8580 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8581 " This means that these rules will randomly find their contents. This can be fixed by"
8582 " setting the tcp-request inspect-delay.\n",
8583 proxy_type_str(curproxy), curproxy->id);
8584 err_code |= ERR_WARN;
8585 }
8586 }
8587
Christopher Fauletd7c91962015-04-30 11:48:27 +02008588 /* Check filter configuration, if any */
8589 cfgerr += flt_check(curproxy);
8590
Willy Tarreauc1a21672009-08-16 22:37:44 +02008591 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008592 if (!curproxy->accept)
8593 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008594
Willy Tarreauc1a21672009-08-16 22:37:44 +02008595 if (curproxy->tcp_req.inspect_delay ||
8596 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008597 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008598
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008599 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008600 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008601 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008602 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008603
8604 /* both TCP and HTTP must check switching rules */
8605 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008606
8607 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008608 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008609 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8610 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008611 if (curproxy->mode == PR_MODE_HTTP) {
8612 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8613 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8614 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008615 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008616 }
8617
8618 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008619 if (curproxy->tcp_req.inspect_delay ||
8620 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8621 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8622
Emeric Brun97679e72010-09-23 17:56:44 +02008623 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8624 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8625
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008626 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008627 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008628 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008629 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008630
8631 /* If the backend does requires RDP cookie persistence, we have to
8632 * enable the corresponding analyser.
8633 */
8634 if (curproxy->options2 & PR_O2_RDPC_PRST)
8635 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008636
8637 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008638 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008639 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8640 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008641 if (curproxy->mode == PR_MODE_HTTP) {
8642 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8643 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8644 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008645 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008646 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008647 }
8648
8649 /***********************************************************/
8650 /* At this point, target names have already been resolved. */
8651 /***********************************************************/
8652
8653 /* Check multi-process mode compatibility */
8654
8655 if (global.nbproc > 1 && global.stats_fe) {
8656 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8657 unsigned long mask;
8658
8659 mask = nbits(global.nbproc);
8660 if (global.stats_fe->bind_proc)
8661 mask &= global.stats_fe->bind_proc;
8662
8663 if (bind_conf->bind_proc)
8664 mask &= bind_conf->bind_proc;
8665
8666 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008667 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008668 break;
8669 }
8670 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8671 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");
8672 }
8673 }
8674
8675 /* Make each frontend inherit bind-process from its listeners when not specified. */
8676 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8677 if (curproxy->bind_proc)
8678 continue;
8679
8680 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8681 unsigned long mask;
8682
Willy Tarreaue428b082015-05-04 21:57:58 +02008683 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008684 curproxy->bind_proc |= mask;
8685 }
8686
8687 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008688 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008689 }
8690
8691 if (global.stats_fe) {
8692 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8693 unsigned long mask;
8694
Cyril Bonté06181952016-02-24 00:14:54 +01008695 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008696 global.stats_fe->bind_proc |= mask;
8697 }
8698 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008699 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008700 }
8701
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008702 /* propagate bindings from frontends to backends. Don't do it if there
8703 * are any fatal errors as we must not call it with unresolved proxies.
8704 */
8705 if (!cfgerr) {
8706 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8707 if (curproxy->cap & PR_CAP_FE)
8708 propagate_processes(curproxy, NULL);
8709 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008710 }
8711
8712 /* Bind each unbound backend to all processes when not specified. */
8713 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8714 if (curproxy->bind_proc)
8715 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008716 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008717 }
8718
8719 /*******************************************************/
8720 /* At this step, all proxies have a non-null bind_proc */
8721 /*******************************************************/
8722
8723 /* perform the final checks before creating tasks */
8724
8725 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8726 struct listener *listener;
8727 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008728
Emeric Brunc52962f2012-11-15 18:28:02 +01008729#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008730 /* Configure SSL for each bind line.
8731 * Note: if configuration fails at some point, the ->ctx member
8732 * remains NULL so that listeners can later detach.
8733 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008734 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008735 int alloc_ctx;
8736
Emeric Brunc52962f2012-11-15 18:28:02 +01008737 if (!bind_conf->is_ssl) {
8738 if (bind_conf->default_ctx) {
8739 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8740 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8741 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008742 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008743 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008744 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008745 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008746 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008747 cfgerr++;
8748 continue;
8749 }
8750
Emeric Brun8dc60392014-05-09 13:52:00 +02008751 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008752 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008753 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8754 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");
8755 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008756 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008757 cfgerr++;
8758 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008759 }
8760
Emeric Brunfc0421f2012-09-07 17:30:07 +02008761 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008762 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008763
8764 /* initialize CA variables if the certificates generation is enabled */
8765 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008766 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008767#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008768
Willy Tarreaue6b98942007-10-29 01:09:36 +01008769 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008770 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008771 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008772 int nbproc;
8773
8774 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008775 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008776 nbits(global.nbproc));
8777
8778 if (!nbproc) /* no intersection between listener and frontend */
8779 nbproc = 1;
8780
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008781 if (!listener->luid) {
8782 /* listener ID not set, use automatic numbering with first
8783 * spare entry starting with next_luid.
8784 */
8785 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8786 listener->conf.id.key = listener->luid = next_id;
8787 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008788 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008789 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008790
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008791 /* enable separate counters */
8792 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008793 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008794 if (!listener->name)
8795 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008796 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008797
Willy Tarreaue6b98942007-10-29 01:09:36 +01008798 if (curproxy->options & PR_O_TCP_NOLING)
8799 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008800 if (!listener->maxconn)
8801 listener->maxconn = curproxy->maxconn;
8802 if (!listener->backlog)
8803 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008804 if (!listener->maxaccept)
8805 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8806
8807 /* we want to have an optimal behaviour on single process mode to
8808 * maximize the work at once, but in multi-process we want to keep
8809 * some fairness between processes, so we target half of the max
8810 * number of events to be balanced over all the processes the proxy
8811 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8812 * used to disable the limit.
8813 */
8814 if (listener->maxaccept > 0) {
8815 if (nbproc > 1)
8816 listener->maxaccept = (listener->maxaccept + 1) / 2;
8817 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8818 }
8819
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008820 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008821 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008822 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008823 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008824
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008825 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
8826 listener->options |= LI_O_TCP_RULES;
8827
Willy Tarreaude3041d2010-05-31 10:56:17 +02008828 if (curproxy->mon_mask.s_addr)
8829 listener->options |= LI_O_CHK_MONNET;
8830
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008831 /* smart accept mode is automatic in HTTP mode */
8832 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008833 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008834 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8835 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008836 }
8837
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008838 /* Release unused SSL configs */
8839 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8840 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008841 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008842#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008843 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008844 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008845 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008846 free(bind_conf->ca_sign_file);
8847 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008848 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008849 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008850 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008851 if(bind_conf->keys_ref) {
8852 free(bind_conf->keys_ref->filename);
8853 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02008854 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008855 free(bind_conf->keys_ref);
8856 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008857#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008858 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008859
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008860 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008861 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008862 int count, maxproc = 0;
8863
8864 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008865 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008866 if (count > maxproc)
8867 maxproc = count;
8868 }
8869 /* backends have 0, frontends have 1 or more */
8870 if (maxproc != 1)
8871 Warning("Proxy '%s': in multi-process mode, stats will be"
8872 " limited to process assigned to the current request.\n",
8873 curproxy->id);
8874
Willy Tarreau102df612014-05-07 23:56:38 +02008875 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8876 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8877 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008878 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008879 }
Willy Tarreau102df612014-05-07 23:56:38 +02008880 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8881 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8882 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008883 }
8884 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008885
8886 /* create the task associated with the proxy */
8887 curproxy->task = task_new();
8888 if (curproxy->task) {
8889 curproxy->task->context = curproxy;
8890 curproxy->task->process = manage_proxy;
8891 /* no need to queue, it will be done automatically if some
8892 * listener gets limited.
8893 */
8894 curproxy->task->expire = TICK_ETERNITY;
8895 } else {
8896 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8897 curproxy->id);
8898 cfgerr++;
8899 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008900 }
8901
Willy Tarreaufbb78422011-06-05 15:38:35 +02008902 /* automatically compute fullconn if not set. We must not do it in the
8903 * loop above because cross-references are not yet fully resolved.
8904 */
8905 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8906 /* If <fullconn> is not set, let's set it to 10% of the sum of
8907 * the possible incoming frontend's maxconns.
8908 */
8909 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
8910 struct proxy *fe;
8911 int total = 0;
8912
8913 /* sum up the number of maxconns of frontends which
8914 * reference this backend at least once or which are
8915 * the same one ('listen').
8916 */
8917 for (fe = proxy; fe; fe = fe->next) {
8918 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008919 int found = 0;
8920
8921 if (!(fe->cap & PR_CAP_FE))
8922 continue;
8923
8924 if (fe == curproxy) /* we're on a "listen" instance */
8925 found = 1;
8926
8927 if (fe->defbe.be == curproxy) /* "default_backend" */
8928 found = 1;
8929
8930 /* check if a "use_backend" rule matches */
8931 if (!found) {
8932 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01008933 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02008934 found = 1;
8935 break;
8936 }
8937 }
8938 }
8939
Willy Tarreaufbb78422011-06-05 15:38:35 +02008940 /* now we've checked all possible ways to reference a backend
8941 * from a frontend.
8942 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02008943 if (!found)
8944 continue;
8945 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02008946 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02008947 /* we have the sum of the maxconns in <total>. We only
8948 * keep 10% of that sum to set the default fullconn, with
8949 * a hard minimum of 1 (to avoid a divide by zero).
8950 */
8951 curproxy->fullconn = (total + 9) / 10;
8952 if (!curproxy->fullconn)
8953 curproxy->fullconn = 1;
8954 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01008955 }
8956
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008957 /*
8958 * Recount currently required checks.
8959 */
8960
8961 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
8962 int optnum;
8963
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008964 for (optnum = 0; cfg_opts[optnum].name; optnum++)
8965 if (curproxy->options & cfg_opts[optnum].val)
8966 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008967
Willy Tarreau66aa61f2009-01-18 21:44:07 +01008968 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
8969 if (curproxy->options2 & cfg_opts2[optnum].val)
8970 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01008971 }
8972
Willy Tarreau0fca4832015-05-01 19:12:05 +02008973 /* compute the required process bindings for the peers */
8974 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
8975 if (curproxy->table.peers.p)
8976 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
8977
Willy Tarreau122541c2011-09-07 21:24:49 +02008978 if (peers) {
8979 struct peers *curpeers = peers, **last;
8980 struct peer *p, *pb;
8981
Willy Tarreau1e273012015-05-01 19:15:17 +02008982 /* Remove all peers sections which don't have a valid listener,
8983 * which are not used by any table, or which are bound to more
8984 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02008985 */
8986 last = &peers;
8987 while (*last) {
8988 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008989
8990 if (curpeers->state == PR_STSTOPPED) {
8991 /* the "disabled" keyword was present */
8992 if (curpeers->peers_fe)
8993 stop_proxy(curpeers->peers_fe);
8994 curpeers->peers_fe = NULL;
8995 }
8996 else if (!curpeers->peers_fe) {
8997 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
8998 curpeers->id, localpeer);
8999 }
David Carliere6c39412015-07-02 07:00:17 +00009000 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009001 /* either it's totally stopped or too much used */
9002 if (curpeers->peers_fe->bind_proc) {
9003 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009004 "running in different processes (%d different ones). "
9005 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009006 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009007 cfgerr++;
9008 }
9009 stop_proxy(curpeers->peers_fe);
9010 curpeers->peers_fe = NULL;
9011 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009012 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009013 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009014 last = &curpeers->next;
9015 continue;
9016 }
9017
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009018 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009019 p = curpeers->remote;
9020 while (p) {
9021 pb = p->next;
9022 free(p->id);
9023 free(p);
9024 p = pb;
9025 }
9026
9027 /* Destroy and unlink this curpeers section.
9028 * Note: curpeers is backed up into *last.
9029 */
9030 free(curpeers->id);
9031 curpeers = curpeers->next;
9032 free(*last);
9033 *last = curpeers;
9034 }
9035 }
9036
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009037 /* initialize stick-tables on backend capable proxies. This must not
9038 * be done earlier because the data size may be discovered while parsing
9039 * other proxies.
9040 */
9041 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9042 if (curproxy->state == PR_STSTOPPED)
9043 continue;
9044
9045 if (!stktable_init(&curproxy->table)) {
9046 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9047 cfgerr++;
9048 }
9049 }
9050
Simon Horman0d16a402015-01-30 11:22:58 +09009051 if (mailers) {
9052 struct mailers *curmailers = mailers, **last;
9053 struct mailer *m, *mb;
9054
9055 /* Remove all mailers sections which don't have a valid listener.
9056 * This can happen when a mailers section is never referenced.
9057 */
9058 last = &mailers;
9059 while (*last) {
9060 curmailers = *last;
9061 if (curmailers->users) {
9062 last = &curmailers->next;
9063 continue;
9064 }
9065
9066 Warning("Removing incomplete section 'mailers %s'.\n",
9067 curmailers->id);
9068
9069 m = curmailers->mailer_list;
9070 while (m) {
9071 mb = m->next;
9072 free(m->id);
9073 free(m);
9074 m = mb;
9075 }
9076
9077 /* Destroy and unlink this curmailers section.
9078 * Note: curmailers is backed up into *last.
9079 */
9080 free(curmailers->id);
9081 curmailers = curmailers->next;
9082 free(*last);
9083 *last = curmailers;
9084 }
9085 }
9086
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009087 /* Update server_state_file_name to backend name if backend is supposed to use
9088 * a server-state file locally defined and none has been provided */
9089 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9090 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9091 curproxy->server_state_file_name == NULL)
9092 curproxy->server_state_file_name = strdup(curproxy->id);
9093 }
9094
Willy Tarreau34eb6712011-10-24 18:15:04 +02009095 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009096 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009097 MEM_F_SHARED);
9098
Willy Tarreaubb925012009-07-23 13:36:36 +02009099 if (cfgerr > 0)
9100 err_code |= ERR_ALERT | ERR_FATAL;
9101 out:
9102 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009103}
9104
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009105/*
9106 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9107 * parsing sessions.
9108 */
9109void cfg_register_keywords(struct cfg_kw_list *kwl)
9110{
9111 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9112}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009113
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009114/*
9115 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9116 */
9117void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9118{
9119 LIST_DEL(&kwl->list);
9120 LIST_INIT(&kwl->list);
9121}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009122
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009123/* this function register new section in the haproxy configuration file.
9124 * <section_name> is the name of this new section and <section_parser>
9125 * is the called parser. If two section declaration have the same name,
9126 * only the first declared is used.
9127 */
9128int cfg_register_section(char *section_name,
9129 int (*section_parser)(const char *, int, char **, int))
9130{
9131 struct cfg_section *cs;
9132
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009133 list_for_each_entry(cs, &sections, list) {
9134 if (strcmp(cs->section_name, section_name) == 0) {
9135 Alert("register section '%s': already registered.\n", section_name);
9136 return 0;
9137 }
9138 }
9139
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009140 cs = calloc(1, sizeof(*cs));
9141 if (!cs) {
9142 Alert("register section '%s': out of memory.\n", section_name);
9143 return 0;
9144 }
9145
9146 cs->section_name = section_name;
9147 cs->section_parser = section_parser;
9148
9149 LIST_ADDQ(&sections, &cs->list);
9150
9151 return 1;
9152}
9153
Willy Tarreaubaaee002006-06-26 02:48:02 +02009154/*
David Carlier845efb52015-09-25 11:49:18 +01009155 * free all config section entries
9156 */
9157void cfg_unregister_sections(void)
9158{
9159 struct cfg_section *cs, *ics;
9160
9161 list_for_each_entry_safe(cs, ics, &sections, list) {
9162 LIST_DEL(&cs->list);
9163 free(cs);
9164 }
9165}
9166
Willy Tarreau659fbf02016-05-26 17:55:28 +02009167__attribute__((constructor))
9168static void cfgparse_init(void)
9169{
9170 /* Register internal sections */
9171 cfg_register_section("listen", cfg_parse_listen);
9172 cfg_register_section("frontend", cfg_parse_listen);
9173 cfg_register_section("backend", cfg_parse_listen);
9174 cfg_register_section("defaults", cfg_parse_listen);
9175 cfg_register_section("global", cfg_parse_global);
9176 cfg_register_section("userlist", cfg_parse_users);
9177 cfg_register_section("peers", cfg_parse_peers);
9178 cfg_register_section("mailers", cfg_parse_mailers);
9179 cfg_register_section("namespace_list", cfg_parse_netns);
9180 cfg_register_section("resolvers", cfg_parse_resolvers);
9181}
9182
David Carlier845efb52015-09-25 11:49:18 +01009183/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009184 * Local variables:
9185 * c-indent-level: 8
9186 * c-basic-offset: 8
9187 * End:
9188 */