blob: 356ae98107d69e8e56e32246179fb1f84c82925f [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 Tarreau620408f2016-10-21 16:37:51 +0200361/* Report a warning if a rule is placed after a 'tcp-request session' rule.
362 * Return 1 if the warning has been emitted, otherwise 0.
363 */
364int warnif_rule_after_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
365{
366 if (!LIST_ISEMPTY(&proxy->tcp_req.l5_rules)) {
367 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request session' rule will still be processed before.\n",
368 file, line, arg);
369 return 1;
370 }
371 return 0;
372}
373
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200374/* Report a warning if a rule is placed after a 'tcp-request content' rule.
375 * Return 1 if the warning has been emitted, otherwise 0.
376 */
377int warnif_rule_after_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
378{
379 if (!LIST_ISEMPTY(&proxy->tcp_req.inspect_rules)) {
380 Warning("parsing [%s:%d] : a '%s' rule placed after a 'tcp-request content' rule will still be processed before.\n",
381 file, line, arg);
382 return 1;
383 }
384 return 0;
385}
386
Willy Tarreau61d18892009-03-31 10:49:21 +0200387/* Report a warning if a rule is placed after a 'block' rule.
388 * Return 1 if the warning has been emitted, otherwise 0.
389 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100390int warnif_rule_after_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200391{
Willy Tarreau353bc9f2014-04-28 22:05:31 +0200392 if (!LIST_ISEMPTY(&proxy->block_rules)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200393 Warning("parsing [%s:%d] : a '%s' rule placed after a 'block' rule will still be processed before.\n",
394 file, line, arg);
395 return 1;
396 }
397 return 0;
398}
399
Willy Tarreau5002f572014-04-23 01:32:02 +0200400/* Report a warning if a rule is placed after an 'http_request' rule.
401 * Return 1 if the warning has been emitted, otherwise 0.
402 */
403int warnif_rule_after_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
404{
405 if (!LIST_ISEMPTY(&proxy->http_req_rules)) {
406 Warning("parsing [%s:%d] : a '%s' rule placed after an 'http-request' rule will still be processed before.\n",
407 file, line, arg);
408 return 1;
409 }
410 return 0;
411}
412
Willy Tarreau61d18892009-03-31 10:49:21 +0200413/* Report a warning if a rule is placed after a reqrewrite rule.
414 * Return 1 if the warning has been emitted, otherwise 0.
415 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100416int warnif_rule_after_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200417{
418 if (proxy->req_exp) {
419 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqxxx' 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 reqadd rule.
427 * Return 1 if the warning has been emitted, otherwise 0.
428 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100429int warnif_rule_after_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200430{
Willy Tarreaudeb9ed82010-01-03 21:03:22 +0100431 if (!LIST_ISEMPTY(&proxy->req_add)) {
Willy Tarreau61d18892009-03-31 10:49:21 +0200432 Warning("parsing [%s:%d] : a '%s' rule placed after a 'reqadd' 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 redirect rule.
440 * Return 1 if the warning has been emitted, otherwise 0.
441 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100442int warnif_rule_after_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200443{
444 if (!LIST_ISEMPTY(&proxy->redirect_rules)) {
445 Warning("parsing [%s:%d] : a '%s' rule placed after a 'redirect' rule will still be processed before.\n",
446 file, line, arg);
447 return 1;
448 }
449 return 0;
450}
451
452/* Report a warning if a rule is placed after a 'use_backend' rule.
453 * Return 1 if the warning has been emitted, otherwise 0.
454 */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100455int warnif_rule_after_use_backend(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200456{
457 if (!LIST_ISEMPTY(&proxy->switching_rules)) {
458 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use_backend' rule will still be processed before.\n",
459 file, line, arg);
460 return 1;
461 }
462 return 0;
463}
464
Willy Tarreauee445d92014-04-23 01:39:04 +0200465/* Report a warning if a rule is placed after a 'use-server' rule.
466 * Return 1 if the warning has been emitted, otherwise 0.
467 */
468int warnif_rule_after_use_server(struct proxy *proxy, const char *file, int line, const char *arg)
469{
470 if (!LIST_ISEMPTY(&proxy->server_rules)) {
471 Warning("parsing [%s:%d] : a '%s' rule placed after a 'use-server' rule will still be processed before.\n",
472 file, line, arg);
473 return 1;
474 }
475 return 0;
476}
477
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200478/* report a warning if a "tcp request connection" rule is dangerously placed */
479int warnif_misplaced_tcp_conn(struct proxy *proxy, const char *file, int line, const char *arg)
480{
Willy Tarreau620408f2016-10-21 16:37:51 +0200481 return warnif_rule_after_tcp_sess(proxy, file, line, arg) ||
482 warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
483 warnif_rule_after_block(proxy, file, line, arg) ||
484 warnif_rule_after_http_req(proxy, file, line, arg) ||
485 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
486 warnif_rule_after_reqadd(proxy, file, line, arg) ||
487 warnif_rule_after_redirect(proxy, file, line, arg) ||
488 warnif_rule_after_use_backend(proxy, file, line, arg) ||
489 warnif_rule_after_use_server(proxy, file, line, arg);
490}
491
492int warnif_misplaced_tcp_sess(struct proxy *proxy, const char *file, int line, const char *arg)
493{
Willy Tarreau3986b9c2014-09-16 15:39:51 +0200494 return warnif_rule_after_tcp_cont(proxy, file, line, arg) ||
495 warnif_rule_after_block(proxy, file, line, arg) ||
496 warnif_rule_after_http_req(proxy, file, line, arg) ||
497 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
498 warnif_rule_after_reqadd(proxy, file, line, arg) ||
499 warnif_rule_after_redirect(proxy, file, line, arg) ||
500 warnif_rule_after_use_backend(proxy, file, line, arg) ||
501 warnif_rule_after_use_server(proxy, file, line, arg);
502}
503
504/* report a warning if a "tcp request content" rule is dangerously placed */
505int warnif_misplaced_tcp_cont(struct proxy *proxy, const char *file, int line, const char *arg)
506{
507 return warnif_rule_after_block(proxy, file, line, arg) ||
508 warnif_rule_after_http_req(proxy, file, line, arg) ||
509 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
510 warnif_rule_after_reqadd(proxy, file, line, arg) ||
511 warnif_rule_after_redirect(proxy, file, line, arg) ||
512 warnif_rule_after_use_backend(proxy, file, line, arg) ||
513 warnif_rule_after_use_server(proxy, file, line, arg);
514}
515
Willy Tarreau61d18892009-03-31 10:49:21 +0200516/* report a warning if a block rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100517int warnif_misplaced_block(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200518{
Willy Tarreau5002f572014-04-23 01:32:02 +0200519 return warnif_rule_after_http_req(proxy, file, line, arg) ||
520 warnif_rule_after_reqxxx(proxy, file, line, arg) ||
521 warnif_rule_after_reqadd(proxy, file, line, arg) ||
522 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200523 warnif_rule_after_use_backend(proxy, file, line, arg) ||
524 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau5002f572014-04-23 01:32:02 +0200525}
526
527/* report a warning if an http-request rule is dangerously placed */
528int warnif_misplaced_http_req(struct proxy *proxy, const char *file, int line, const char *arg)
529{
Willy Tarreau61d18892009-03-31 10:49:21 +0200530 return warnif_rule_after_reqxxx(proxy, file, line, arg) ||
531 warnif_rule_after_reqadd(proxy, file, line, arg) ||
532 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200533 warnif_rule_after_use_backend(proxy, file, line, arg) ||
534 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200535}
536
537/* report a warning if a reqxxx rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100538int warnif_misplaced_reqxxx(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200539{
540 return warnif_rule_after_reqadd(proxy, file, line, arg) ||
541 warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200542 warnif_rule_after_use_backend(proxy, file, line, arg) ||
543 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200544}
545
546/* report a warning if a reqadd rule is dangerously placed */
Willy Tarreau3ec18a02010-01-28 19:01:34 +0100547int warnif_misplaced_reqadd(struct proxy *proxy, const char *file, int line, const char *arg)
Willy Tarreau61d18892009-03-31 10:49:21 +0200548{
549 return warnif_rule_after_redirect(proxy, file, line, arg) ||
Willy Tarreauee445d92014-04-23 01:39:04 +0200550 warnif_rule_after_use_backend(proxy, file, line, arg) ||
551 warnif_rule_after_use_server(proxy, file, line, arg);
552}
553
554/* report a warning if a redirect rule is dangerously placed */
555int warnif_misplaced_redirect(struct proxy *proxy, const char *file, int line, const char *arg)
556{
557 return warnif_rule_after_use_backend(proxy, file, line, arg) ||
558 warnif_rule_after_use_server(proxy, file, line, arg);
Willy Tarreau61d18892009-03-31 10:49:21 +0200559}
560
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100561/* Report it if a request ACL condition uses some keywords that are incompatible
562 * with the place where the ACL is used. It returns either 0 or ERR_WARN so that
563 * its result can be or'ed with err_code. Note that <cond> may be NULL and then
564 * will be ignored.
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100565 */
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100566static int warnif_cond_conflicts(const struct acl_cond *cond, unsigned int where, const char *file, int line)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100567{
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100568 const struct acl *acl;
Willy Tarreau93fddf12013-03-31 22:59:32 +0200569 const char *kw;
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100570
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100571 if (!cond)
Willy Tarreauf1e98b82010-01-28 17:59:39 +0100572 return 0;
573
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100574 acl = acl_cond_conflicts(cond, where);
575 if (acl) {
576 if (acl->name && *acl->name)
577 Warning("parsing [%s:%d] : acl '%s' will never match because it only involves keywords that are incompatible with '%s'\n",
578 file, line, acl->name, sample_ckp_names(where));
579 else
580 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 +0200581 file, line, LIST_ELEM(acl->expr.n, struct acl_expr *, list)->kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100582 return ERR_WARN;
583 }
584 if (!acl_cond_kw_conflicts(cond, where, &acl, &kw))
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100585 return 0;
586
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100587 if (acl->name && *acl->name)
588 Warning("parsing [%s:%d] : acl '%s' involves keywords '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200589 file, line, acl->name, kw, sample_ckp_names(where));
Willy Tarreaua91d0a52013-03-25 08:12:18 +0100590 else
591 Warning("parsing [%s:%d] : anonymous acl involves keyword '%s' which is incompatible with '%s'\n",
Willy Tarreau93fddf12013-03-31 22:59:32 +0200592 file, line, kw, sample_ckp_names(where));
Willy Tarreaufdb563c2010-01-31 15:43:27 +0100593 return ERR_WARN;
594}
595
Willy Tarreaubaaee002006-06-26 02:48:02 +0200596/*
Willy Tarreau058e9072009-07-20 09:30:05 +0200597 * parse a line in a <global> section. Returns the error code, 0 if OK, or
598 * any combination of :
599 * - ERR_ABORT: must abort ASAP
600 * - ERR_FATAL: we can continue parsing but not start the service
601 * - ERR_WARN: a warning has been emitted
602 * - ERR_ALERT: an alert has been emitted
603 * Only the two first ones can stop processing, the two others are just
604 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200605 */
Willy Tarreau3842f002009-06-14 11:39:52 +0200606int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200607{
Willy Tarreau058e9072009-07-20 09:30:05 +0200608 int err_code = 0;
Willy Tarreau0a3dd742012-05-08 19:47:01 +0200609 char *errmsg = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200610
611 if (!strcmp(args[0], "global")) { /* new section */
612 /* no option, nothing special to do */
William Lallemand6e62fb62015-04-28 16:55:23 +0200613 alertif_too_many_args(0, file, linenum, args, &err_code);
Willy Tarreau058e9072009-07-20 09:30:05 +0200614 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200615 }
Emeric Brunc8e8d122012-10-02 18:42:10 +0200616 else if (!strcmp(args[0], "ca-base")) {
617#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200618 if(alertif_too_many_args(1, file, linenum, args, &err_code))
619 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200620 if (global.ca_base != NULL) {
621 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
622 err_code |= ERR_ALERT;
623 goto out;
624 }
625 if (*(args[1]) == 0) {
626 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
627 err_code |= ERR_ALERT | ERR_FATAL;
628 goto out;
629 }
630 global.ca_base = strdup(args[1]);
631#else
632 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
633 err_code |= ERR_ALERT | ERR_FATAL;
634 goto out;
635#endif
636 }
637 else if (!strcmp(args[0], "crt-base")) {
638#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +0200639 if (alertif_too_many_args(1, file, linenum, args, &err_code))
640 goto out;
Emeric Brunc8e8d122012-10-02 18:42:10 +0200641 if (global.crt_base != NULL) {
642 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
643 err_code |= ERR_ALERT;
644 goto out;
645 }
646 if (*(args[1]) == 0) {
647 Alert("parsing [%s:%d] : '%s' expects a directory path as an argument.\n", file, linenum, args[0]);
648 err_code |= ERR_ALERT | ERR_FATAL;
649 goto out;
650 }
651 global.crt_base = strdup(args[1]);
652#else
653 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
654 err_code |= ERR_ALERT | ERR_FATAL;
655 goto out;
656#endif
657 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200658 else if (!strcmp(args[0], "daemon")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200659 if (alertif_too_many_args(0, file, linenum, args, &err_code))
660 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200661 global.mode |= MODE_DAEMON;
662 }
663 else if (!strcmp(args[0], "debug")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200664 if (alertif_too_many_args(0, file, linenum, args, &err_code))
665 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200666 global.mode |= MODE_DEBUG;
667 }
668 else if (!strcmp(args[0], "noepoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200669 if (alertif_too_many_args(0, file, linenum, args, &err_code))
670 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100671 global.tune.options &= ~GTUNE_USE_EPOLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200672 }
Willy Tarreaude99e992007-04-16 00:53:59 +0200673 else if (!strcmp(args[0], "nokqueue")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200674 if (alertif_too_many_args(0, file, linenum, args, &err_code))
675 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100676 global.tune.options &= ~GTUNE_USE_KQUEUE;
Willy Tarreaude99e992007-04-16 00:53:59 +0200677 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200678 else if (!strcmp(args[0], "nopoll")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200679 if (alertif_too_many_args(0, file, linenum, args, &err_code))
680 goto out;
Willy Tarreau43b78992009-01-25 15:42:27 +0100681 global.tune.options &= ~GTUNE_USE_POLL;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200682 }
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100683 else if (!strcmp(args[0], "nosplice")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200684 if (alertif_too_many_args(0, file, linenum, args, &err_code))
685 goto out;
Willy Tarreau3ab68cf2009-01-25 16:03:28 +0100686 global.tune.options &= ~GTUNE_USE_SPLICE;
687 }
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200688 else if (!strcmp(args[0], "nogetaddrinfo")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200689 if (alertif_too_many_args(0, file, linenum, args, &err_code))
690 goto out;
Nenad Merdanovic88afe032014-04-14 15:56:58 +0200691 global.tune.options &= ~GTUNE_USE_GAI;
692 }
Lukas Tribusa0bcbdc2016-09-12 21:42:20 +0000693 else if (!strcmp(args[0], "noreuseport")) {
694 if (alertif_too_many_args(0, file, linenum, args, &err_code))
695 goto out;
696 global.tune.options &= ~GTUNE_USE_REUSEPORT;
697 }
Willy Tarreaubaaee002006-06-26 02:48:02 +0200698 else if (!strcmp(args[0], "quiet")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200699 if (alertif_too_many_args(0, file, linenum, args, &err_code))
700 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200701 global.mode |= MODE_QUIET;
702 }
Willy Tarreau1db37712007-06-03 17:16:49 +0200703 else if (!strcmp(args[0], "tune.maxpollevents")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200704 if (alertif_too_many_args(1, file, linenum, args, &err_code))
705 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200706 if (global.tune.maxpollevents != 0) {
707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200708 err_code |= ERR_ALERT;
709 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200710 }
711 if (*(args[1]) == 0) {
712 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200713 err_code |= ERR_ALERT | ERR_FATAL;
714 goto out;
Willy Tarreau1db37712007-06-03 17:16:49 +0200715 }
716 global.tune.maxpollevents = atol(args[1]);
717 }
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100718 else if (!strcmp(args[0], "tune.maxaccept")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200719 if (alertif_too_many_args(1, file, linenum, args, &err_code))
720 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100721 if (global.tune.maxaccept != 0) {
722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200723 err_code |= ERR_ALERT;
724 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100725 }
726 if (*(args[1]) == 0) {
727 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +0200728 err_code |= ERR_ALERT | ERR_FATAL;
729 goto out;
Willy Tarreaua0250ba2008-01-06 11:22:57 +0100730 }
731 global.tune.maxaccept = atol(args[1]);
732 }
Willy Tarreau43961d52010-10-04 20:39:20 +0200733 else if (!strcmp(args[0], "tune.chksize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200734 if (alertif_too_many_args(1, file, linenum, args, &err_code))
735 goto out;
Willy Tarreau43961d52010-10-04 20:39:20 +0200736 if (*(args[1]) == 0) {
737 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
738 err_code |= ERR_ALERT | ERR_FATAL;
739 goto out;
740 }
741 global.tune.chksize = atol(args[1]);
742 }
Willy Tarreaub22fc302015-12-14 12:04:35 +0100743 else if (!strcmp(args[0], "tune.recv_enough")) {
744 if (alertif_too_many_args(1, file, linenum, args, &err_code))
745 goto out;
746 if (*(args[1]) == 0) {
747 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
748 err_code |= ERR_ALERT | ERR_FATAL;
749 goto out;
750 }
751 global.tune.recv_enough = atol(args[1]);
752 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200753#ifdef USE_OPENSSL
Emeric Brun8dc60392014-05-09 13:52:00 +0200754 else if (!strcmp(args[0], "tune.ssl.force-private-cache")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200755 if (alertif_too_many_args(0, file, linenum, args, &err_code))
756 goto out;
Emeric Brun8dc60392014-05-09 13:52:00 +0200757 global.tune.sslprivatecache = 1;
758 }
Willy Tarreau6ec58db2012-11-16 16:32:15 +0100759 else if (!strcmp(args[0], "tune.ssl.cachesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200760 if (alertif_too_many_args(1, file, linenum, args, &err_code))
761 goto out;
Emeric Brunfc32aca2012-09-03 12:10:29 +0200762 if (*(args[1]) == 0) {
763 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
764 err_code |= ERR_ALERT | ERR_FATAL;
765 goto out;
766 }
767 global.tune.sslcachesize = atol(args[1]);
768 }
Emeric Brun4f65bff2012-11-16 15:11:00 +0100769 else if (!strcmp(args[0], "tune.ssl.lifetime")) {
770 unsigned int ssllifetime;
771 const char *res;
772
William Lallemand1a748ae2015-05-19 16:37:23 +0200773 if (alertif_too_many_args(1, file, linenum, args, &err_code))
774 goto out;
Emeric Brun4f65bff2012-11-16 15:11:00 +0100775 if (*(args[1]) == 0) {
776 Alert("parsing [%s:%d] : '%s' expects ssl sessions <lifetime> in seconds as argument.\n", file, linenum, args[0]);
777 err_code |= ERR_ALERT | ERR_FATAL;
778 goto out;
779 }
780
781 res = parse_time_err(args[1], &ssllifetime, TIME_UNIT_S);
782 if (res) {
783 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
784 file, linenum, *res, args[0]);
785 err_code |= ERR_ALERT | ERR_FATAL;
786 goto out;
787 }
788
789 global.tune.ssllifetime = ssllifetime;
790 }
Willy Tarreaubfd59462013-02-21 07:46:09 +0100791 else if (!strcmp(args[0], "tune.ssl.maxrecord")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200792 if (alertif_too_many_args(1, file, linenum, args, &err_code))
793 goto out;
Willy Tarreaubfd59462013-02-21 07:46:09 +0100794 if (*(args[1]) == 0) {
795 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
796 err_code |= ERR_ALERT | ERR_FATAL;
797 goto out;
798 }
799 global.tune.ssl_max_record = atol(args[1]);
800 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200801#ifndef OPENSSL_NO_DH
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200802 else if (!strcmp(args[0], "tune.ssl.default-dh-param")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200803 if (alertif_too_many_args(1, file, linenum, args, &err_code))
804 goto out;
Remi Gacognef46cd6e2014-06-12 14:58:40 +0200805 if (*(args[1]) == 0) {
806 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
807 err_code |= ERR_ALERT | ERR_FATAL;
808 goto out;
809 }
810 global.tune.ssl_default_dh_param = atol(args[1]);
811 if (global.tune.ssl_default_dh_param < 1024) {
812 Alert("parsing [%s:%d] : '%s' expects a value >= 1024.\n", file, linenum, args[0]);
813 err_code |= ERR_ALERT | ERR_FATAL;
814 goto out;
815 }
816 }
Emeric Brunfc32aca2012-09-03 12:10:29 +0200817#endif
Christopher Faulet31af49d2015-06-09 17:29:50 +0200818 else if (!strcmp(args[0], "tune.ssl.ssl-ctx-cache-size")) {
819 if (alertif_too_many_args(1, file, linenum, args, &err_code))
820 goto out;
821 if (*(args[1]) == 0) {
822 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
823 err_code |= ERR_ALERT | ERR_FATAL;
824 goto out;
825 }
826 global.tune.ssl_ctx_cache = atoi(args[1]);
827 if (global.tune.ssl_ctx_cache < 0) {
828 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
829 file, linenum, args[0]);
830 err_code |= ERR_ALERT | ERR_FATAL;
831 goto out;
832 }
833 }
Remi Gacogne47783ef2015-05-29 15:53:22 +0200834#endif
Willy Tarreau33cb0652014-12-23 22:52:37 +0100835 else if (!strcmp(args[0], "tune.buffers.limit")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200836 if (alertif_too_many_args(1, file, linenum, args, &err_code))
837 goto out;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100838 if (*(args[1]) == 0) {
839 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
840 err_code |= ERR_ALERT | ERR_FATAL;
841 goto out;
842 }
843 global.tune.buf_limit = atol(args[1]);
844 if (global.tune.buf_limit) {
845 if (global.tune.buf_limit < 3)
846 global.tune.buf_limit = 3;
847 if (global.tune.buf_limit <= global.tune.reserved_bufs)
848 global.tune.buf_limit = global.tune.reserved_bufs + 1;
849 }
850 }
Willy Tarreau1058ae72014-12-23 22:40:40 +0100851 else if (!strcmp(args[0], "tune.buffers.reserve")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200852 if (alertif_too_many_args(1, file, linenum, args, &err_code))
853 goto out;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100854 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.reserved_bufs = atol(args[1]);
860 if (global.tune.reserved_bufs < 2)
861 global.tune.reserved_bufs = 2;
Willy Tarreau33cb0652014-12-23 22:52:37 +0100862 if (global.tune.buf_limit && global.tune.buf_limit <= global.tune.reserved_bufs)
863 global.tune.buf_limit = global.tune.reserved_bufs + 1;
Willy Tarreau1058ae72014-12-23 22:40:40 +0100864 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200865 else if (!strcmp(args[0], "tune.bufsize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200866 if (alertif_too_many_args(1, file, linenum, args, &err_code))
867 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200868 if (*(args[1]) == 0) {
869 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
870 err_code |= ERR_ALERT | ERR_FATAL;
871 goto out;
872 }
873 global.tune.bufsize = atol(args[1]);
Willy Tarreau9b694542015-09-28 13:49:53 +0200874 if (global.tune.bufsize <= 0) {
875 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
876 err_code |= ERR_ALERT | ERR_FATAL;
877 goto out;
878 }
Willy Tarreau19d14ef2012-10-29 16:51:55 +0100879 chunk_init(&trash, realloc(trash.str, global.tune.bufsize), global.tune.bufsize);
Willy Tarreau2819e992013-12-13 14:41:10 +0100880 alloc_trash_buffers(global.tune.bufsize);
Willy Tarreau27a674e2009-08-17 07:23:33 +0200881 }
882 else if (!strcmp(args[0], "tune.maxrewrite")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200883 if (alertif_too_many_args(1, file, linenum, args, &err_code))
884 goto out;
Willy Tarreau27a674e2009-08-17 07:23:33 +0200885 if (*(args[1]) == 0) {
886 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
887 err_code |= ERR_ALERT | ERR_FATAL;
888 goto out;
889 }
890 global.tune.maxrewrite = atol(args[1]);
Willy Tarreau27097842015-09-28 13:53:23 +0200891 if (global.tune.maxrewrite < 0) {
892 Alert("parsing [%s:%d] : '%s' expects a positive integer argument.\n", file, linenum, args[0]);
893 err_code |= ERR_ALERT | ERR_FATAL;
894 goto out;
895 }
Willy Tarreau27a674e2009-08-17 07:23:33 +0200896 }
Willy Tarreau7e312732014-02-12 16:35:14 +0100897 else if (!strcmp(args[0], "tune.idletimer")) {
898 unsigned int idle;
899 const char *res;
900
William Lallemand1a748ae2015-05-19 16:37:23 +0200901 if (alertif_too_many_args(1, file, linenum, args, &err_code))
902 goto out;
Willy Tarreau7e312732014-02-12 16:35:14 +0100903 if (*(args[1]) == 0) {
904 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
905 err_code |= ERR_ALERT | ERR_FATAL;
906 goto out;
907 }
908
909 res = parse_time_err(args[1], &idle, TIME_UNIT_MS);
910 if (res) {
911 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
912 file, linenum, *res, args[0]);
913 err_code |= ERR_ALERT | ERR_FATAL;
914 goto out;
915 }
916
917 if (idle > 65535) {
918 Alert("parsing [%s:%d] : '%s' expects a timer value between 0 and 65535 ms.\n", file, linenum, args[0]);
919 err_code |= ERR_ALERT | ERR_FATAL;
920 goto out;
921 }
922 global.tune.idle_timer = idle;
923 }
Willy Tarreaue803de22010-01-21 17:43:04 +0100924 else if (!strcmp(args[0], "tune.rcvbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200925 if (alertif_too_many_args(1, file, linenum, args, &err_code))
926 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100927 if (global.tune.client_rcvbuf != 0) {
928 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
929 err_code |= ERR_ALERT;
930 goto out;
931 }
932 if (*(args[1]) == 0) {
933 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
934 err_code |= ERR_ALERT | ERR_FATAL;
935 goto out;
936 }
937 global.tune.client_rcvbuf = atol(args[1]);
938 }
939 else if (!strcmp(args[0], "tune.rcvbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200940 if (alertif_too_many_args(1, file, linenum, args, &err_code))
941 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100942 if (global.tune.server_rcvbuf != 0) {
943 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
944 err_code |= ERR_ALERT;
945 goto out;
946 }
947 if (*(args[1]) == 0) {
948 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
949 err_code |= ERR_ALERT | ERR_FATAL;
950 goto out;
951 }
952 global.tune.server_rcvbuf = atol(args[1]);
953 }
954 else if (!strcmp(args[0], "tune.sndbuf.client")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200955 if (alertif_too_many_args(1, file, linenum, args, &err_code))
956 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100957 if (global.tune.client_sndbuf != 0) {
958 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
959 err_code |= ERR_ALERT;
960 goto out;
961 }
962 if (*(args[1]) == 0) {
963 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
964 err_code |= ERR_ALERT | ERR_FATAL;
965 goto out;
966 }
967 global.tune.client_sndbuf = atol(args[1]);
968 }
969 else if (!strcmp(args[0], "tune.sndbuf.server")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200970 if (alertif_too_many_args(1, file, linenum, args, &err_code))
971 goto out;
Willy Tarreaue803de22010-01-21 17:43:04 +0100972 if (global.tune.server_sndbuf != 0) {
973 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
974 err_code |= ERR_ALERT;
975 goto out;
976 }
977 if (*(args[1]) == 0) {
978 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
979 err_code |= ERR_ALERT | ERR_FATAL;
980 goto out;
981 }
982 global.tune.server_sndbuf = atol(args[1]);
983 }
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200984 else if (!strcmp(args[0], "tune.pipesize")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200985 if (alertif_too_many_args(1, file, linenum, args, &err_code))
986 goto out;
Willy Tarreaubd9a0a72011-10-23 21:14:29 +0200987 if (*(args[1]) == 0) {
988 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
989 err_code |= ERR_ALERT | ERR_FATAL;
990 goto out;
991 }
992 global.tune.pipesize = atol(args[1]);
993 }
Willy Tarreau193b8c62012-11-22 00:17:38 +0100994 else if (!strcmp(args[0], "tune.http.cookielen")) {
William Lallemand1a748ae2015-05-19 16:37:23 +0200995 if (alertif_too_many_args(1, file, linenum, args, &err_code))
996 goto out;
Willy Tarreau193b8c62012-11-22 00:17:38 +0100997 if (*(args[1]) == 0) {
998 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
999 err_code |= ERR_ALERT | ERR_FATAL;
1000 goto out;
1001 }
1002 global.tune.cookie_len = atol(args[1]) + 1;
1003 }
Willy Tarreauac1932d2011-10-24 19:14:41 +02001004 else if (!strcmp(args[0], "tune.http.maxhdr")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001005 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1006 goto out;
Willy Tarreauac1932d2011-10-24 19:14:41 +02001007 if (*(args[1]) == 0) {
1008 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1009 err_code |= ERR_ALERT | ERR_FATAL;
1010 goto out;
1011 }
1012 global.tune.max_http_hdr = atol(args[1]);
1013 }
William Lallemanda509e4c2012-11-07 16:54:34 +01001014 else if (!strcmp(args[0], "tune.zlib.memlevel")) {
1015#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001016 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1017 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001018 if (*args[1]) {
1019 global.tune.zlibmemlevel = atoi(args[1]);
1020 if (global.tune.zlibmemlevel < 1 || global.tune.zlibmemlevel > 9) {
1021 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1022 file, linenum, args[0]);
1023 err_code |= ERR_ALERT | ERR_FATAL;
1024 goto out;
1025 }
1026 } else {
1027 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1028 file, linenum, args[0]);
1029 err_code |= ERR_ALERT | ERR_FATAL;
1030 goto out;
1031 }
1032#else
1033 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1034 err_code |= ERR_ALERT | ERR_FATAL;
1035 goto out;
1036#endif
1037 }
1038 else if (!strcmp(args[0], "tune.zlib.windowsize")) {
1039#ifdef USE_ZLIB
William Lallemand1a748ae2015-05-19 16:37:23 +02001040 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1041 goto out;
William Lallemanda509e4c2012-11-07 16:54:34 +01001042 if (*args[1]) {
1043 global.tune.zlibwindowsize = atoi(args[1]);
1044 if (global.tune.zlibwindowsize < 8 || global.tune.zlibwindowsize > 15) {
1045 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1046 file, linenum, args[0]);
1047 err_code |= ERR_ALERT | ERR_FATAL;
1048 goto out;
1049 }
1050 } else {
1051 Alert("parsing [%s:%d] : '%s' expects a numeric value between 8 and 15\n",
1052 file, linenum, args[0]);
1053 err_code |= ERR_ALERT | ERR_FATAL;
1054 goto out;
1055 }
1056#else
1057 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1058 err_code |= ERR_ALERT | ERR_FATAL;
1059 goto out;
1060#endif
1061 }
William Lallemandf3747832012-11-09 12:33:10 +01001062 else if (!strcmp(args[0], "tune.comp.maxlevel")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001063 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1064 goto out;
William Lallemandf3747832012-11-09 12:33:10 +01001065 if (*args[1]) {
1066 global.tune.comp_maxlevel = atoi(args[1]);
1067 if (global.tune.comp_maxlevel < 1 || global.tune.comp_maxlevel > 9) {
1068 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1069 file, linenum, args[0]);
1070 err_code |= ERR_ALERT | ERR_FATAL;
1071 goto out;
1072 }
1073 } else {
1074 Alert("parsing [%s:%d] : '%s' expects a numeric value between 1 and 9\n",
1075 file, linenum, args[0]);
1076 err_code |= ERR_ALERT | ERR_FATAL;
1077 goto out;
1078 }
1079 }
Willy Tarreauf3045d22015-04-29 16:24:50 +02001080 else if (!strcmp(args[0], "tune.pattern.cache-size")) {
1081 if (*args[1]) {
1082 global.tune.pattern_cache = atoi(args[1]);
1083 if (global.tune.pattern_cache < 0) {
1084 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1085 file, linenum, args[0]);
1086 err_code |= ERR_ALERT | ERR_FATAL;
1087 goto out;
1088 }
1089 } else {
1090 Alert("parsing [%s:%d] : '%s' expects a positive numeric value\n",
1091 file, linenum, args[0]);
1092 err_code |= ERR_ALERT | ERR_FATAL;
1093 goto out;
1094 }
1095 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001096 else if (!strcmp(args[0], "uid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001097 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1098 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001099 if (global.uid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001100 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001101 err_code |= ERR_ALERT;
1102 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001103 }
1104 if (*(args[1]) == 0) {
1105 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001106 err_code |= ERR_ALERT | ERR_FATAL;
1107 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001108 }
Baptiste Assmann79fee6a2016-03-11 17:10:04 +01001109 if (strl2irc(args[1], strlen(args[1]), &global.uid) != 0) {
1110 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]);
1111 err_code |= ERR_WARN;
1112 goto out;
1113 }
1114
Willy Tarreaubaaee002006-06-26 02:48:02 +02001115 }
1116 else if (!strcmp(args[0], "gid")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001117 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1118 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001119 if (global.gid != 0) {
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001120 Alert("parsing [%s:%d] : group/gid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001121 err_code |= ERR_ALERT;
1122 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001123 }
1124 if (*(args[1]) == 0) {
1125 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001126 err_code |= ERR_ALERT | ERR_FATAL;
1127 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001128 }
Baptiste Assmann776e5182016-03-11 17:21:15 +01001129 if (strl2irc(args[1], strlen(args[1]), &global.gid) != 0) {
1130 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]);
1131 err_code |= ERR_WARN;
1132 goto out;
1133 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001134 }
Simon Horman98637e52014-06-20 12:30:16 +09001135 else if (!strcmp(args[0], "external-check")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001136 if (alertif_too_many_args(0, file, linenum, args, &err_code))
1137 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09001138 global.external_check = 1;
1139 }
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001140 /* user/group name handling */
1141 else if (!strcmp(args[0], "user")) {
1142 struct passwd *ha_user;
William Lallemand1a748ae2015-05-19 16:37:23 +02001143 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1144 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001145 if (global.uid != 0) {
1146 Alert("parsing [%s:%d] : user/uid already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001147 err_code |= ERR_ALERT;
1148 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001149 }
1150 errno = 0;
1151 ha_user = getpwnam(args[1]);
1152 if (ha_user != NULL) {
1153 global.uid = (int)ha_user->pw_uid;
1154 }
1155 else {
1156 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 +02001157 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001158 }
1159 }
1160 else if (!strcmp(args[0], "group")) {
1161 struct group *ha_group;
William Lallemand1a748ae2015-05-19 16:37:23 +02001162 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1163 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001164 if (global.gid != 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02001165 Alert("parsing [%s:%d] : gid/group was already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001166 err_code |= ERR_ALERT;
1167 goto out;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001168 }
1169 errno = 0;
1170 ha_group = getgrnam(args[1]);
1171 if (ha_group != NULL) {
1172 global.gid = (int)ha_group->gr_gid;
1173 }
1174 else {
1175 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 +02001176 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau95c20ac2007-03-25 15:39:23 +02001177 }
1178 }
1179 /* end of user/group name handling*/
Willy Tarreaubaaee002006-06-26 02:48:02 +02001180 else if (!strcmp(args[0], "nbproc")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001181 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1182 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001183 if (*(args[1]) == 0) {
1184 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001185 err_code |= ERR_ALERT | ERR_FATAL;
1186 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001187 }
1188 global.nbproc = atol(args[1]);
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001189 if (global.nbproc < 1 || global.nbproc > LONGBITS) {
1190 Alert("parsing [%s:%d] : '%s' must be between 1 and %d (was %d).\n",
1191 file, linenum, args[0], LONGBITS, global.nbproc);
1192 err_code |= ERR_ALERT | ERR_FATAL;
1193 goto out;
1194 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001195 }
1196 else if (!strcmp(args[0], "maxconn")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001197 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1198 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001199 if (global.maxconn != 0) {
1200 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001201 err_code |= ERR_ALERT;
1202 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001203 }
1204 if (*(args[1]) == 0) {
1205 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001206 err_code |= ERR_ALERT | ERR_FATAL;
1207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001208 }
1209 global.maxconn = atol(args[1]);
1210#ifdef SYSTEM_MAXCONN
1211 if (global.maxconn > DEFAULT_MAXCONN && cfg_maxconn <= DEFAULT_MAXCONN) {
1212 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);
1213 global.maxconn = DEFAULT_MAXCONN;
Willy Tarreau058e9072009-07-20 09:30:05 +02001214 err_code |= ERR_ALERT;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001215 }
1216#endif /* SYSTEM_MAXCONN */
1217 }
Willy Tarreau403edff2012-09-06 11:58:37 +02001218 else if (!strcmp(args[0], "maxsslconn")) {
1219#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001220 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1221 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001222 if (*(args[1]) == 0) {
1223 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1224 err_code |= ERR_ALERT | ERR_FATAL;
1225 goto out;
1226 }
1227 global.maxsslconn = atol(args[1]);
1228#else
Emeric Brun0914df82012-10-02 18:45:42 +02001229 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1230 err_code |= ERR_ALERT | ERR_FATAL;
1231 goto out;
Willy Tarreau403edff2012-09-06 11:58:37 +02001232#endif
1233 }
Willy Tarreau610f04b2014-02-13 11:36:41 +01001234 else if (!strcmp(args[0], "ssl-default-bind-ciphers")) {
1235#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001236 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1237 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001238 if (*(args[1]) == 0) {
1239 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1240 err_code |= ERR_ALERT | ERR_FATAL;
1241 goto out;
1242 }
1243 free(global.listen_default_ciphers);
1244 global.listen_default_ciphers = strdup(args[1]);
1245#else
1246 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1247 err_code |= ERR_ALERT | ERR_FATAL;
1248 goto out;
1249#endif
1250 }
1251 else if (!strcmp(args[0], "ssl-default-server-ciphers")) {
1252#ifdef USE_OPENSSL
William Lallemand1a748ae2015-05-19 16:37:23 +02001253 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1254 goto out;
Willy Tarreau610f04b2014-02-13 11:36:41 +01001255 if (*(args[1]) == 0) {
1256 Alert("parsing [%s:%d] : '%s' expects a cipher suite as an argument.\n", file, linenum, args[0]);
1257 err_code |= ERR_ALERT | ERR_FATAL;
1258 goto out;
1259 }
1260 free(global.connect_default_ciphers);
1261 global.connect_default_ciphers = strdup(args[1]);
1262#else
1263 Alert("parsing [%s:%d] : '%s' is not implemented.\n", file, linenum, args[0]);
1264 err_code |= ERR_ALERT | ERR_FATAL;
1265 goto out;
1266#endif
1267 }
Remi Gacogne47783ef2015-05-29 15:53:22 +02001268#ifdef USE_OPENSSL
1269#ifndef OPENSSL_NO_DH
1270 else if (!strcmp(args[0], "ssl-dh-param-file")) {
1271 if (*(args[1]) == 0) {
1272 Alert("parsing [%s:%d] : '%s' expects a file path as an argument.\n", file, linenum, args[0]);
1273 err_code |= ERR_ALERT | ERR_FATAL;
1274 goto out;
1275 }
1276 if (ssl_sock_load_global_dh_param_from_file(args[1])) {
1277 Alert("parsing [%s:%d] : '%s': unable to load DH parameters from file <%s>.\n", file, linenum, args[0], args[1]);
1278 err_code |= ERR_ALERT | ERR_FATAL;
1279 goto out;
1280 }
1281 }
1282#endif
1283#endif
Emeric Brun850efd52014-01-29 12:24:34 +01001284 else if (!strcmp(args[0], "ssl-server-verify")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001285 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1286 goto out;
Emeric Brun850efd52014-01-29 12:24:34 +01001287 if (*(args[1]) == 0) {
1288 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1289 err_code |= ERR_ALERT | ERR_FATAL;
1290 goto out;
1291 }
1292 if (strcmp(args[1],"none") == 0)
1293 global.ssl_server_verify = SSL_SERVER_VERIFY_NONE;
1294 else if (strcmp(args[1],"required") == 0)
1295 global.ssl_server_verify = SSL_SERVER_VERIFY_REQUIRED;
1296 else {
1297 Alert("parsing [%s:%d] : '%s' expects 'none' or 'required' as argument.\n", file, linenum, args[0]);
1298 err_code |= ERR_ALERT | ERR_FATAL;
1299 goto out;
1300 }
1301 }
Willy Tarreau81c25d02011-09-07 15:17:21 +02001302 else if (!strcmp(args[0], "maxconnrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001303 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1304 goto out;
Willy Tarreau81c25d02011-09-07 15:17:21 +02001305 if (global.cps_lim != 0) {
1306 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1307 err_code |= ERR_ALERT;
1308 goto out;
1309 }
1310 if (*(args[1]) == 0) {
1311 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1312 err_code |= ERR_ALERT | ERR_FATAL;
1313 goto out;
1314 }
1315 global.cps_lim = atol(args[1]);
1316 }
Willy Tarreau93e7c002013-10-07 18:51:07 +02001317 else if (!strcmp(args[0], "maxsessrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001318 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1319 goto out;
Willy Tarreau93e7c002013-10-07 18:51:07 +02001320 if (global.sps_lim != 0) {
1321 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1322 err_code |= ERR_ALERT;
1323 goto out;
1324 }
1325 if (*(args[1]) == 0) {
1326 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1327 err_code |= ERR_ALERT | ERR_FATAL;
1328 goto out;
1329 }
1330 global.sps_lim = atol(args[1]);
1331 }
Willy Tarreaue43d5322013-10-07 20:01:52 +02001332 else if (!strcmp(args[0], "maxsslrate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001333 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1334 goto out;
Willy Tarreaue43d5322013-10-07 20:01:52 +02001335 if (global.ssl_lim != 0) {
1336 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1337 err_code |= ERR_ALERT;
1338 goto out;
1339 }
1340 if (*(args[1]) == 0) {
1341 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1342 err_code |= ERR_ALERT | ERR_FATAL;
1343 goto out;
1344 }
1345 global.ssl_lim = atol(args[1]);
1346 }
William Lallemandd85f9172012-11-09 17:05:39 +01001347 else if (!strcmp(args[0], "maxcomprate")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001348 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1349 goto out;
William Lallemandd85f9172012-11-09 17:05:39 +01001350 if (*(args[1]) == 0) {
1351 Alert("parsing [%s:%d] : '%s' expects an integer argument in kb/s.\n", file, linenum, args[0]);
1352 err_code |= ERR_ALERT | ERR_FATAL;
1353 goto out;
1354 }
1355 global.comp_rate_lim = atoi(args[1]) * 1024;
1356 }
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001357 else if (!strcmp(args[0], "maxpipes")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001358 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1359 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001360 if (global.maxpipes != 0) {
1361 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001362 err_code |= ERR_ALERT;
1363 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001364 }
1365 if (*(args[1]) == 0) {
1366 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001367 err_code |= ERR_ALERT | ERR_FATAL;
1368 goto out;
Willy Tarreau3ec79b92009-01-18 20:39:42 +01001369 }
1370 global.maxpipes = atol(args[1]);
1371 }
William Lallemand9d5f5482012-11-07 16:12:57 +01001372 else if (!strcmp(args[0], "maxzlibmem")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001373 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1374 goto out;
William Lallemand9d5f5482012-11-07 16:12:57 +01001375 if (*(args[1]) == 0) {
1376 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
1377 err_code |= ERR_ALERT | ERR_FATAL;
1378 goto out;
1379 }
William Lallemande3a7d992012-11-20 11:25:20 +01001380 global.maxzlibmem = atol(args[1]) * 1024L * 1024L;
William Lallemand9d5f5482012-11-07 16:12:57 +01001381 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001382 else if (!strcmp(args[0], "maxcompcpuusage")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001383 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1384 goto out;
William Lallemand072a2bf2012-11-20 17:01:01 +01001385 if (*(args[1]) == 0) {
1386 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1387 err_code |= ERR_ALERT | ERR_FATAL;
1388 goto out;
1389 }
1390 compress_min_idle = 100 - atoi(args[1]);
Willy Tarreaucb2699a2013-01-24 16:25:38 +01001391 if (compress_min_idle > 100) {
William Lallemand072a2bf2012-11-20 17:01:01 +01001392 Alert("parsing [%s:%d] : '%s' expects an integer argument between 0 and 100.\n", file, linenum, args[0]);
1393 err_code |= ERR_ALERT | ERR_FATAL;
1394 goto out;
1395 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001396 }
William Lallemand072a2bf2012-11-20 17:01:01 +01001397
Willy Tarreaubaaee002006-06-26 02:48:02 +02001398 else if (!strcmp(args[0], "ulimit-n")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001399 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1400 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001401 if (global.rlimit_nofile != 0) {
1402 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001403 err_code |= ERR_ALERT;
1404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001405 }
1406 if (*(args[1]) == 0) {
1407 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001408 err_code |= ERR_ALERT | ERR_FATAL;
1409 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001410 }
1411 global.rlimit_nofile = atol(args[1]);
1412 }
1413 else if (!strcmp(args[0], "chroot")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001414 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1415 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001416 if (global.chroot != NULL) {
1417 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001418 err_code |= ERR_ALERT;
1419 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001420 }
1421 if (*(args[1]) == 0) {
1422 Alert("parsing [%s:%d] : '%s' expects a directory as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001423 err_code |= ERR_ALERT | ERR_FATAL;
1424 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001425 }
1426 global.chroot = strdup(args[1]);
1427 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001428 else if (!strcmp(args[0], "description")) {
1429 int i, len=0;
1430 char *d;
1431
1432 if (!*args[1]) {
1433 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
1434 file, linenum, args[0]);
1435 err_code |= ERR_ALERT | ERR_FATAL;
1436 goto out;
1437 }
1438
Willy Tarreau348acfe2014-04-14 15:00:39 +02001439 for (i = 1; *args[i]; i++)
1440 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001441
1442 if (global.desc)
1443 free(global.desc);
1444
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02001445 global.desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001446
Willy Tarreau348acfe2014-04-14 15:00:39 +02001447 d += snprintf(d, global.desc + len - d, "%s", args[1]);
1448 for (i = 2; *args[i]; i++)
1449 d += snprintf(d, global.desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001450 }
1451 else if (!strcmp(args[0], "node")) {
1452 int i;
1453 char c;
1454
William Lallemand1a748ae2015-05-19 16:37:23 +02001455 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1456 goto out;
1457
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001458 for (i=0; args[1][i]; i++) {
1459 c = args[1][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01001460 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
1461 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001462 break;
1463 }
1464
1465 if (!i || args[1][i]) {
1466 Alert("parsing [%s:%d]: '%s' requires valid node name - non-empty string"
1467 " with digits(0-9), letters(A-Z, a-z), dot(.), hyphen(-) or underscode(_).\n",
1468 file, linenum, args[0]);
1469 err_code |= ERR_ALERT | ERR_FATAL;
1470 goto out;
1471 }
1472
1473 if (global.node)
1474 free(global.node);
1475
1476 global.node = strdup(args[1]);
1477 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001478 else if (!strcmp(args[0], "pidfile")) {
William Lallemand1a748ae2015-05-19 16:37:23 +02001479 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1480 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001481 if (global.pidfile != NULL) {
1482 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001483 err_code |= ERR_ALERT;
1484 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001485 }
1486 if (*(args[1]) == 0) {
1487 Alert("parsing [%s:%d] : '%s' expects a file name as an argument.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001488 err_code |= ERR_ALERT | ERR_FATAL;
1489 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001490 }
1491 global.pidfile = strdup(args[1]);
1492 }
Emeric Bruned760922010-10-22 17:59:25 +02001493 else if (!strcmp(args[0], "unix-bind")) {
1494 int cur_arg = 1;
1495 while (*(args[cur_arg])) {
1496 if (!strcmp(args[cur_arg], "prefix")) {
1497 if (global.unix_bind.prefix != NULL) {
1498 Alert("parsing [%s:%d] : unix-bind '%s' already specified. Continuing.\n", file, linenum, args[cur_arg]);
1499 err_code |= ERR_ALERT;
1500 cur_arg += 2;
1501 continue;
1502 }
1503
1504 if (*(args[cur_arg+1]) == 0) {
1505 Alert("parsing [%s:%d] : unix_bind '%s' expects a path as an argument.\n", file, linenum, args[cur_arg]);
1506 err_code |= ERR_ALERT | ERR_FATAL;
1507 goto out;
1508 }
1509 global.unix_bind.prefix = strdup(args[cur_arg+1]);
1510 cur_arg += 2;
1511 continue;
1512 }
1513
1514 if (!strcmp(args[cur_arg], "mode")) {
1515
1516 global.unix_bind.ux.mode = strtol(args[cur_arg + 1], NULL, 8);
1517 cur_arg += 2;
1518 continue;
1519 }
1520
1521 if (!strcmp(args[cur_arg], "uid")) {
1522
1523 global.unix_bind.ux.uid = atol(args[cur_arg + 1 ]);
1524 cur_arg += 2;
1525 continue;
1526 }
1527
1528 if (!strcmp(args[cur_arg], "gid")) {
1529
1530 global.unix_bind.ux.gid = atol(args[cur_arg + 1 ]);
1531 cur_arg += 2;
1532 continue;
1533 }
1534
1535 if (!strcmp(args[cur_arg], "user")) {
1536 struct passwd *user;
1537
1538 user = getpwnam(args[cur_arg + 1]);
1539 if (!user) {
1540 Alert("parsing [%s:%d] : '%s' : '%s' unknown user.\n",
1541 file, linenum, args[0], args[cur_arg + 1 ]);
1542 err_code |= ERR_ALERT | ERR_FATAL;
1543 goto out;
1544 }
1545
1546 global.unix_bind.ux.uid = user->pw_uid;
1547 cur_arg += 2;
1548 continue;
1549 }
1550
1551 if (!strcmp(args[cur_arg], "group")) {
1552 struct group *group;
1553
1554 group = getgrnam(args[cur_arg + 1]);
1555 if (!group) {
1556 Alert("parsing [%s:%d] : '%s' : '%s' unknown group.\n",
1557 file, linenum, args[0], args[cur_arg + 1 ]);
1558 err_code |= ERR_ALERT | ERR_FATAL;
1559 goto out;
1560 }
1561
1562 global.unix_bind.ux.gid = group->gr_gid;
1563 cur_arg += 2;
1564 continue;
1565 }
1566
Willy Tarreaub48f9582011-09-05 01:17:06 +02001567 Alert("parsing [%s:%d] : '%s' only supports the 'prefix', 'mode', 'uid', 'gid', 'user' and 'group' options.\n",
Emeric Bruned760922010-10-22 17:59:25 +02001568 file, linenum, args[0]);
1569 err_code |= ERR_ALERT | ERR_FATAL;
1570 goto out;
1571 }
1572 }
William Lallemand0f99e342011-10-12 17:50:54 +02001573 else if (!strcmp(args[0], "log") && kwm == KWM_NO) { /* no log */
1574 /* delete previous herited or defined syslog servers */
1575 struct logsrv *back;
1576 struct logsrv *tmp;
1577
1578 if (*(args[1]) != 0) {
1579 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
1580 err_code |= ERR_ALERT | ERR_FATAL;
1581 goto out;
1582 }
1583
1584 list_for_each_entry_safe(tmp, back, &global.logsrvs, list) {
1585 LIST_DEL(&tmp->list);
1586 free(tmp);
1587 }
1588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001589 else if (!strcmp(args[0], "log")) { /* syslog server address */
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001590 struct sockaddr_storage *sk;
1591 int port1, port2;
William Lallemand0f99e342011-10-12 17:50:54 +02001592 struct logsrv *logsrv;
Willy Tarreau18324f52014-06-27 18:10:07 +02001593 int arg = 0;
1594 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02001595
William Lallemand1a748ae2015-05-19 16:37:23 +02001596 if (alertif_too_many_args(8, file, linenum, args, &err_code)) /* does not strictly check optional arguments */
1597 goto out;
1598
Willy Tarreaubaaee002006-06-26 02:48:02 +02001599 if (*(args[1]) == 0 || *(args[2]) == 0) {
1600 Alert("parsing [%s:%d] : '%s' expects <address> and <facility> as arguments.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001601 err_code |= ERR_ALERT | ERR_FATAL;
1602 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001603 }
William Lallemand0f99e342011-10-12 17:50:54 +02001604
Vincent Bernat02779b62016-04-03 13:48:43 +02001605 logsrv = calloc(1, sizeof(*logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02001606
Willy Tarreau18324f52014-06-27 18:10:07 +02001607 /* just after the address, a length may be specified */
1608 if (strcmp(args[arg+2], "len") == 0) {
1609 len = atoi(args[arg+3]);
1610 if (len < 80 || len > 65535) {
1611 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
1612 file, linenum, args[arg+3]);
1613 err_code |= ERR_ALERT | ERR_FATAL;
1614 goto out;
1615 }
1616 logsrv->maxlen = len;
1617
1618 /* skip these two args */
1619 arg += 2;
1620 }
1621 else
1622 logsrv->maxlen = MAX_SYSLOG_LEN;
1623
1624 if (logsrv->maxlen > global.max_syslog_len) {
1625 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02001626 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
1627 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
1628 logline = my_realloc2(logline, global.max_syslog_len + 1);
1629 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02001630 }
1631
Dragan Dosen1322d092015-09-22 16:05:32 +02001632 /* after the length, a format may be specified */
1633 if (strcmp(args[arg+2], "format") == 0) {
1634 logsrv->format = get_log_format(args[arg+3]);
1635 if (logsrv->format < 0) {
1636 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
1637 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01001638 free(logsrv);
Dragan Dosen1322d092015-09-22 16:05:32 +02001639 goto out;
1640 }
1641
1642 /* skip these two args */
1643 arg += 2;
1644 }
1645
David Carlier97880bb2016-04-08 10:35:26 +01001646 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code)) {
1647 free(logsrv);
William Lallemand1a748ae2015-05-19 16:37:23 +02001648 goto out;
David Carlier97880bb2016-04-08 10:35:26 +01001649 }
William Lallemand1a748ae2015-05-19 16:37:23 +02001650
Willy Tarreau18324f52014-06-27 18:10:07 +02001651 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02001652 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001653 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001654 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001655 logsrv->facility = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001656 }
1657
William Lallemand0f99e342011-10-12 17:50:54 +02001658 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02001659 if (*(args[arg+3])) {
1660 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02001661 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001662 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001663 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001664 logsrv->level = 0;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001665 }
1666 }
1667
William Lallemand0f99e342011-10-12 17:50:54 +02001668 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02001669 if (*(args[arg+4])) {
1670 logsrv->minlvl = get_log_level(args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02001671 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02001672 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001673 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001674 logsrv->minlvl = 0;
Willy Tarreauf7edefa2009-05-10 17:20:05 +02001675 }
1676 }
1677
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02001678 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001679 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01001680 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001681 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001682 free(logsrv);
1683 goto out;
1684 }
1685 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001686
Willy Tarreau9b435bc2013-03-06 15:02:49 +01001687 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001688 if (port1 != port2) {
1689 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
1690 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001691 err_code |= ERR_ALERT | ERR_FATAL;
William Lallemand0f99e342011-10-12 17:50:54 +02001692 free(logsrv);
Willy Tarreaud5191e72010-02-09 20:50:45 +01001693 goto out;
1694 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001695
William Lallemand0f99e342011-10-12 17:50:54 +02001696 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01001697 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02001698 set_host_port(&logsrv->addr, SYSLOG_PORT);
Robert Tsai81ae1952007-12-05 10:47:29 +01001699 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001700
William Lallemand0f99e342011-10-12 17:50:54 +02001701 LIST_ADDQ(&global.logsrvs, &logsrv->list);
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001702 }
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001703 else if (!strcmp(args[0], "log-send-hostname")) { /* set the hostname in syslog header */
1704 char *name;
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001705
1706 if (global.log_send_hostname != NULL) {
1707 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1708 err_code |= ERR_ALERT;
1709 goto out;
1710 }
1711
1712 if (*(args[1]))
1713 name = args[1];
1714 else
1715 name = hostname;
1716
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001717 free(global.log_send_hostname);
Dragan Dosenc8cfa7b2015-09-28 13:28:21 +02001718 global.log_send_hostname = strdup(name);
Joe Williamsdf5b38f2010-12-29 17:05:48 +01001719 }
Baptiste Assmann6bc89362015-08-23 09:22:25 +02001720 else if (!strcmp(args[0], "server-state-base")) { /* path base where HAProxy can find server state files */
1721 if (global.server_state_base != NULL) {
1722 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1723 err_code |= ERR_ALERT;
1724 goto out;
1725 }
1726
1727 if (!*(args[1])) {
1728 Alert("parsing [%s:%d] : '%s' expects one argument: a directory path.\n", file, linenum, args[0]);
1729 err_code |= ERR_FATAL;
1730 goto out;
1731 }
1732
1733 global.server_state_base = strdup(args[1]);
1734 }
Baptiste Assmanne0882262015-08-23 09:54:31 +02001735 else if (!strcmp(args[0], "server-state-file")) { /* path to the file where HAProxy can load the server states */
1736 if (global.server_state_file != NULL) {
1737 Alert("parsing [%s:%d] : '%s' already specified. Continuing.\n", file, linenum, args[0]);
1738 err_code |= ERR_ALERT;
1739 goto out;
1740 }
1741
1742 if (!*(args[1])) {
1743 Alert("parsing [%s:%d] : '%s' expect one argument: a file path.\n", file, linenum, args[0]);
1744 err_code |= ERR_FATAL;
1745 goto out;
1746 }
1747
1748 global.server_state_file = strdup(args[1]);
1749 }
Kevinm48936af2010-12-22 16:08:21 +00001750 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
William Lallemand1a748ae2015-05-19 16:37:23 +02001751 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1752 goto out;
Kevinm48936af2010-12-22 16:08:21 +00001753 if (*(args[1]) == 0) {
1754 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
1755 err_code |= ERR_ALERT | ERR_FATAL;
1756 goto out;
1757 }
Dragan Dosen43885c72015-10-01 13:18:13 +02001758 chunk_destroy(&global.log_tag);
1759 chunk_initstr(&global.log_tag, strdup(args[1]));
Kevinm48936af2010-12-22 16:08:21 +00001760 }
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001761 else if (!strcmp(args[0], "spread-checks")) { /* random time between checks (0-50) */
William Lallemand1a748ae2015-05-19 16:37:23 +02001762 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1763 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001764 if (global.spread_checks != 0) {
1765 Alert("parsing [%s:%d]: spread-checks already specified. Continuing.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001766 err_code |= ERR_ALERT;
1767 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001768 }
1769 if (*(args[1]) == 0) {
1770 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02001771 err_code |= ERR_ALERT | ERR_FATAL;
1772 goto out;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001773 }
1774 global.spread_checks = atol(args[1]);
1775 if (global.spread_checks < 0 || global.spread_checks > 50) {
1776 Alert("parsing [%s:%d]: 'spread-checks' needs a positive value in range 0..50.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02001777 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzkib304dc72007-10-14 23:40:01 +02001778 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001779 }
Willy Tarreau1746eec2014-04-25 10:46:47 +02001780 else if (!strcmp(args[0], "max-spread-checks")) { /* maximum time between first and last check */
1781 const char *err;
1782 unsigned int val;
1783
William Lallemand1a748ae2015-05-19 16:37:23 +02001784 if (alertif_too_many_args(1, file, linenum, args, &err_code))
1785 goto out;
Willy Tarreau1746eec2014-04-25 10:46:47 +02001786 if (*(args[1]) == 0) {
1787 Alert("parsing [%s:%d]: '%s' expects an integer argument (0..50).\n", file, linenum, args[0]);
1788 err_code |= ERR_ALERT | ERR_FATAL;
1789 goto out;
1790 }
1791
1792 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
1793 if (err) {
1794 Alert("parsing [%s:%d]: unsupported character '%c' in '%s' (wants an integer delay).\n", file, linenum, *err, args[0]);
1795 err_code |= ERR_ALERT | ERR_FATAL;
1796 }
1797 global.max_spread_checks = val;
1798 if (global.max_spread_checks < 0) {
1799 Alert("parsing [%s:%d]: '%s' needs a positive delay in milliseconds.\n",file, linenum, args[0]);
1800 err_code |= ERR_ALERT | ERR_FATAL;
1801 }
1802 }
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001803 else if (strcmp(args[0], "cpu-map") == 0) { /* map a process list to a CPU set */
1804#ifdef USE_CPU_AFFINITY
1805 int cur_arg, i;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001806 unsigned long proc = 0;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001807 unsigned long cpus = 0;
1808
1809 if (strcmp(args[1], "all") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001810 proc = ~0UL;
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001811 else if (strcmp(args[1], "odd") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001812 proc = ~0UL/3UL; /* 0x555....555 */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001813 else if (strcmp(args[1], "even") == 0)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001814 proc = (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001815 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001816 proc = atol(args[1]);
1817 if (proc >= 1 && proc <= LONGBITS)
1818 proc = 1UL << (proc - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001819 }
1820
1821 if (!proc || !*args[2]) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001822 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",
1823 file, linenum, args[0], LONGBITS, LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001824 err_code |= ERR_ALERT | ERR_FATAL;
1825 goto out;
1826 }
1827
1828 cur_arg = 2;
1829 while (*args[cur_arg]) {
1830 unsigned int low, high;
1831
Willy Tarreau83d84cf2012-11-22 01:04:31 +01001832 if (isdigit((int)*args[cur_arg])) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001833 char *dash = strchr(args[cur_arg], '-');
1834
1835 low = high = str2uic(args[cur_arg]);
1836 if (dash)
1837 high = str2uic(dash + 1);
1838
1839 if (high < low) {
1840 unsigned int swap = low;
1841 low = high;
1842 high = swap;
1843 }
1844
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001845 if (high >= LONGBITS) {
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001846 Alert("parsing [%s:%d]: %s supports CPU numbers from 0 to %d.\n",
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001847 file, linenum, args[0], LONGBITS - 1);
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001848 err_code |= ERR_ALERT | ERR_FATAL;
1849 goto out;
1850 }
1851
1852 while (low <= high)
1853 cpus |= 1UL << low++;
1854 }
1855 else {
1856 Alert("parsing [%s:%d]: %s : '%s' is not a CPU range.\n",
1857 file, linenum, args[0], args[cur_arg]);
1858 err_code |= ERR_ALERT | ERR_FATAL;
1859 goto out;
1860 }
1861 cur_arg++;
1862 }
Willy Tarreaua9db57e2013-01-18 11:29:29 +01001863 for (i = 0; i < LONGBITS; i++)
1864 if (proc & (1UL << i))
Willy Tarreaufc6c0322012-11-16 16:12:27 +01001865 global.cpu_map[i] = cpus;
1866#else
1867 Alert("parsing [%s:%d] : '%s' is not enabled, please check build options for USE_CPU_AFFINITY.\n", file, linenum, args[0]);
1868 err_code |= ERR_ALERT | ERR_FATAL;
1869 goto out;
1870#endif
1871 }
Willy Tarreau1d549722016-02-16 12:41:57 +01001872 else if (strcmp(args[0], "setenv") == 0 || strcmp(args[0], "presetenv") == 0) {
1873 if (alertif_too_many_args(3, file, linenum, args, &err_code))
1874 goto out;
1875
1876 if (*(args[2]) == 0) {
1877 Alert("parsing [%s:%d]: '%s' expects a name and a value.\n", file, linenum, args[0]);
1878 err_code |= ERR_ALERT | ERR_FATAL;
1879 goto out;
1880 }
1881
1882 /* "setenv" overwrites, "presetenv" only sets if not yet set */
1883 if (setenv(args[1], args[2], (args[0][0] == 's')) != 0) {
1884 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[1], strerror(errno));
1885 err_code |= ERR_ALERT | ERR_FATAL;
1886 goto out;
1887 }
1888 }
1889 else if (!strcmp(args[0], "unsetenv")) {
1890 int arg;
1891
1892 if (*(args[1]) == 0) {
1893 Alert("parsing [%s:%d]: '%s' expects at least one variable name.\n", file, linenum, args[0]);
1894 err_code |= ERR_ALERT | ERR_FATAL;
1895 goto out;
1896 }
1897
1898 for (arg = 1; *args[arg]; arg++) {
1899 if (unsetenv(args[arg]) != 0) {
1900 Alert("parsing [%s:%d]: '%s' failed on variable '%s' : %s.\n", file, linenum, args[0], args[arg], strerror(errno));
1901 err_code |= ERR_ALERT | ERR_FATAL;
1902 goto out;
1903 }
1904 }
1905 }
1906 else if (!strcmp(args[0], "resetenv")) {
1907 extern char **environ;
1908 char **env = environ;
1909
1910 /* args contain variable names to keep, one per argument */
1911 while (*env) {
1912 int arg;
1913
1914 /* look for current variable in among all those we want to keep */
1915 for (arg = 1; *args[arg]; arg++) {
1916 if (strncmp(*env, args[arg], strlen(args[arg])) == 0 &&
1917 (*env)[strlen(args[arg])] == '=')
1918 break;
1919 }
1920
1921 /* delete this variable */
1922 if (!*args[arg]) {
1923 char *delim = strchr(*env, '=');
1924
1925 if (!delim || delim - *env >= trash.size) {
1926 Alert("parsing [%s:%d]: '%s' failed to unset invalid variable '%s'.\n", file, linenum, args[0], *env);
1927 err_code |= ERR_ALERT | ERR_FATAL;
1928 goto out;
1929 }
1930
1931 memcpy(trash.str, *env, delim - *env);
1932 trash.str[delim - *env] = 0;
1933
1934 if (unsetenv(trash.str) != 0) {
1935 Alert("parsing [%s:%d]: '%s' failed to unset variable '%s' : %s.\n", file, linenum, args[0], *env, strerror(errno));
1936 err_code |= ERR_ALERT | ERR_FATAL;
1937 goto out;
1938 }
1939 }
1940 else
1941 env++;
1942 }
1943 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02001944 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001945 struct cfg_kw_list *kwl;
1946 int index;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001947 int rc;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001948
1949 list_for_each_entry(kwl, &cfg_keywords.list, list) {
1950 for (index = 0; kwl->kw[index].kw != NULL; index++) {
1951 if (kwl->kw[index].section != CFG_GLOBAL)
1952 continue;
1953 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
Willy Tarreau28a47d62012-09-18 20:02:48 +02001954 rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02001955 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001956 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001957 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001958 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02001959 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001960 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001961 err_code |= ERR_WARN;
1962 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02001963 }
Willy Tarreau058e9072009-07-20 09:30:05 +02001964 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02001965 }
1966 }
1967 }
1968
Willy Tarreaubaaee002006-06-26 02:48:02 +02001969 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "global");
Willy Tarreau058e9072009-07-20 09:30:05 +02001970 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001971 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02001972
Willy Tarreau058e9072009-07-20 09:30:05 +02001973 out:
Willy Tarreau0a3dd742012-05-08 19:47:01 +02001974 free(errmsg);
Willy Tarreau058e9072009-07-20 09:30:05 +02001975 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02001976}
1977
Willy Tarreau915e1eb2009-06-22 15:48:36 +02001978void init_default_instance()
Willy Tarreaubaaee002006-06-26 02:48:02 +02001979{
Willy Tarreau97cb7802010-01-03 20:23:58 +01001980 init_new_proxy(&defproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02001981 defproxy.mode = PR_MODE_TCP;
1982 defproxy.state = PR_STNEW;
1983 defproxy.maxconn = cfg_maxpconn;
1984 defproxy.conn_retries = CONN_RETRIES;
Joseph Lynch726ab712015-05-11 23:25:34 -07001985 defproxy.redispatch_after = 0;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04001986 defproxy.lbprm.chash.balance_factor = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01001987
Simon Horman66183002013-02-23 10:16:43 +09001988 defproxy.defsrv.check.inter = DEF_CHKINTR;
1989 defproxy.defsrv.check.fastinter = 0;
1990 defproxy.defsrv.check.downinter = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001991 defproxy.defsrv.agent.inter = DEF_CHKINTR;
1992 defproxy.defsrv.agent.fastinter = 0;
1993 defproxy.defsrv.agent.downinter = 0;
Simon Horman58c32972013-11-25 10:46:38 +09001994 defproxy.defsrv.check.rise = DEF_RISETIME;
1995 defproxy.defsrv.check.fall = DEF_FALLTIME;
1996 defproxy.defsrv.agent.rise = DEF_AGENT_RISETIME;
1997 defproxy.defsrv.agent.fall = DEF_AGENT_FALLTIME;
Willy Tarreau5b3a2022012-09-28 15:01:02 +02001998 defproxy.defsrv.check.port = 0;
Simon Hormand60d6912013-11-25 10:46:36 +09001999 defproxy.defsrv.agent.port = 0;
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002000 defproxy.defsrv.maxqueue = 0;
2001 defproxy.defsrv.minconn = 0;
2002 defproxy.defsrv.maxconn = 0;
2003 defproxy.defsrv.slowstart = 0;
2004 defproxy.defsrv.onerror = DEF_HANA_ONERR;
2005 defproxy.defsrv.consecutive_errors_limit = DEF_HANA_ERRLIMIT;
2006 defproxy.defsrv.uweight = defproxy.defsrv.iweight = 1;
Simon Horman64e34162015-02-06 11:11:57 +09002007
2008 defproxy.email_alert.level = LOG_ALERT;
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002009 defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002010}
2011
Willy Tarreauade5ec42010-01-28 19:33:49 +01002012
Willy Tarreau63af98d2014-05-18 08:11:41 +02002013/* This function createss a new req* or rsp* rule to the proxy. It compiles the
2014 * regex and may return the ERR_WARN bit, and error bits such as ERR_ALERT and
2015 * ERR_FATAL in case of error.
2016 */
Willy Tarreauade5ec42010-01-28 19:33:49 +01002017static int create_cond_regex_rule(const char *file, int line,
2018 struct proxy *px, int dir, int action, int flags,
2019 const char *cmd, const char *reg, const char *repl,
2020 const char **cond_start)
2021{
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002022 struct my_regex *preg = NULL;
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002023 char *errmsg = NULL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002024 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002025 char *error;
Willy Tarreau63af98d2014-05-18 08:11:41 +02002026 int ret_code = 0;
Willy Tarreau5321c422010-01-28 20:35:13 +01002027 struct acl_cond *cond = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002028 int cs;
2029 int cap;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002030
2031 if (px == &defproxy) {
2032 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002033 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002034 goto err;
2035 }
2036
2037 if (*reg == 0) {
2038 Alert("parsing [%s:%d] : '%s' expects <regex> as an argument.\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
2043 if (warnifnotcap(px, PR_CAP_RS, file, line, cmd, NULL))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002044 ret_code |= ERR_WARN;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002045
Willy Tarreau5321c422010-01-28 20:35:13 +01002046 if (cond_start &&
2047 (strcmp(*cond_start, "if") == 0 || strcmp(*cond_start, "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02002048 if ((cond = build_acl_cond(file, line, px, cond_start, &errmsg)) == NULL) {
2049 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
2050 file, line, cmd, errmsg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002051 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002052 goto err;
2053 }
2054 }
2055 else if (cond_start && **cond_start) {
2056 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
2057 file, line, cmd, *cond_start);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002058 ret_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau5321c422010-01-28 20:35:13 +01002059 goto err;
2060 }
2061
Willy Tarreau63af98d2014-05-18 08:11:41 +02002062 ret_code |= warnif_cond_conflicts(cond,
Willy Tarreaua91d0a52013-03-25 08:12:18 +01002063 (dir == SMP_OPT_DIR_REQ) ?
2064 ((px->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR) :
2065 ((px->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR),
2066 file, line);
Willy Tarreau5321c422010-01-28 20:35:13 +01002067
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002068 preg = calloc(1, sizeof(*preg));
Willy Tarreauade5ec42010-01-28 19:33:49 +01002069 if (!preg) {
2070 Alert("parsing [%s:%d] : '%s' : not enough memory to build regex.\n", file, line, cmd);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002071 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002072 goto err;
2073 }
2074
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002075 cs = !(flags & REG_ICASE);
2076 cap = !(flags & REG_NOSUB);
2077 error = NULL;
2078 if (!regex_comp(reg, preg, cs, cap, &error)) {
2079 Alert("parsing [%s:%d] : '%s' : regular expression '%s' : %s\n", file, line, cmd, reg, error);
2080 free(error);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002081 ret_code = ERR_ALERT | ERR_FATAL;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002082 goto err;
2083 }
2084
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002085 err = chain_regex((dir == SMP_OPT_DIR_REQ) ? &px->req_exp : &px->rsp_exp,
Willy Tarreau5321c422010-01-28 20:35:13 +01002086 preg, action, repl ? strdup(repl) : NULL, cond);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002087 if (repl && err) {
2088 Alert("parsing [%s:%d] : '%s' : invalid character or unterminated sequence in replacement string near '%c'.\n",
2089 file, line, cmd, *err);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002090 ret_code |= ERR_ALERT | ERR_FATAL;
2091 goto err_free;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002092 }
2093
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02002094 if (dir == SMP_OPT_DIR_REQ && warnif_misplaced_reqxxx(px, file, line, cmd))
Willy Tarreau63af98d2014-05-18 08:11:41 +02002095 ret_code |= ERR_WARN;
2096
2097 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002098
Willy Tarreau63af98d2014-05-18 08:11:41 +02002099 err_free:
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002100 regex_free(preg);
Willy Tarreauade5ec42010-01-28 19:33:49 +01002101 err:
2102 free(preg);
Willy Tarreau63af98d2014-05-18 08:11:41 +02002103 free(errmsg);
2104 return ret_code;
Willy Tarreauade5ec42010-01-28 19:33:49 +01002105}
2106
Willy Tarreaubaaee002006-06-26 02:48:02 +02002107/*
William Lallemand51097192015-04-14 16:35:22 +02002108 * Parse a line in a <listen>, <frontend> or <backend> section.
Willy Tarreau93893792009-07-23 13:19:11 +02002109 * Returns the error code, 0 if OK, or any combination of :
2110 * - ERR_ABORT: must abort ASAP
2111 * - ERR_FATAL: we can continue parsing but not start the service
2112 * - ERR_WARN: a warning has been emitted
2113 * - ERR_ALERT: an alert has been emitted
2114 * Only the two first ones can stop processing, the two others are just
2115 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02002116 */
Emeric Brun32da3c42010-09-23 18:39:19 +02002117int cfg_parse_peers(const char *file, int linenum, char **args, int kwm)
2118{
2119 static struct peers *curpeers = NULL;
2120 struct peer *newpeer = NULL;
2121 const char *err;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002122 struct bind_conf *bind_conf;
2123 struct listener *l;
Emeric Brun32da3c42010-09-23 18:39:19 +02002124 int err_code = 0;
Willy Tarreau902636f2013-03-10 19:44:48 +01002125 char *errmsg = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002126
2127 if (strcmp(args[0], "peers") == 0) { /* new peers section */
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002128 if (!*args[1]) {
2129 Alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum);
Willy Tarreau54984722014-02-16 08:20:13 +01002130 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002131 goto out;
2132 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002133
William Lallemand6e62fb62015-04-28 16:55:23 +02002134 if (alertif_too_many_args(1, file, linenum, args, &err_code))
2135 goto out;
2136
Emeric Brun32da3c42010-09-23 18:39:19 +02002137 err = invalid_char(args[1]);
2138 if (err) {
2139 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2140 file, linenum, *err, args[0], args[1]);
Willy Tarreau54984722014-02-16 08:20:13 +01002141 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau0dbbf312013-03-05 11:31:55 +01002142 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002143 }
2144
2145 for (curpeers = peers; curpeers != NULL; curpeers = curpeers->next) {
2146 /*
2147 * If there are two proxies with the same name only following
2148 * combinations are allowed:
2149 */
2150 if (strcmp(curpeers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002151 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 +02002152 file, linenum, args[1], curpeers->conf.file, curpeers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002153 err_code |= ERR_ALERT | ERR_FATAL;
Emeric Brun32da3c42010-09-23 18:39:19 +02002154 }
2155 }
2156
Vincent Bernat02779b62016-04-03 13:48:43 +02002157 if ((curpeers = calloc(1, sizeof(*curpeers))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002158 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2159 err_code |= ERR_ALERT | ERR_ABORT;
2160 goto out;
2161 }
2162
2163 curpeers->next = peers;
2164 peers = curpeers;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002165 curpeers->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002166 curpeers->conf.line = linenum;
2167 curpeers->last_change = now.tv_sec;
2168 curpeers->id = strdup(args[1]);
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002169 curpeers->state = PR_STNEW;
Emeric Brun32da3c42010-09-23 18:39:19 +02002170 }
2171 else if (strcmp(args[0], "peer") == 0) { /* peer definition */
David du Colombier6f5ccb12011-03-10 22:26:24 +01002172 struct sockaddr_storage *sk;
Willy Tarreau2aa38802013-02-20 19:20:59 +01002173 int port1, port2;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002174 struct protocol *proto;
Emeric Brun32da3c42010-09-23 18:39:19 +02002175
2176 if (!*args[2]) {
2177 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2178 file, linenum, args[0]);
2179 err_code |= ERR_ALERT | ERR_FATAL;
2180 goto out;
2181 }
2182
2183 err = invalid_char(args[1]);
2184 if (err) {
2185 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2186 file, linenum, *err, args[1]);
2187 err_code |= ERR_ALERT | ERR_FATAL;
2188 goto out;
2189 }
2190
Vincent Bernat02779b62016-04-03 13:48:43 +02002191 if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) {
Emeric Brun32da3c42010-09-23 18:39:19 +02002192 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2193 err_code |= ERR_ALERT | ERR_ABORT;
2194 goto out;
2195 }
2196
2197 /* the peers are linked backwards first */
2198 curpeers->count++;
2199 newpeer->next = curpeers->remote;
2200 curpeers->remote = newpeer;
Willy Tarreau8113a5d2012-10-04 08:01:43 +02002201 newpeer->conf.file = strdup(file);
Emeric Brun32da3c42010-09-23 18:39:19 +02002202 newpeer->conf.line = linenum;
2203
2204 newpeer->last_change = now.tv_sec;
2205 newpeer->id = strdup(args[1]);
2206
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002207 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002208 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01002209 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau2aa38802013-02-20 19:20:59 +01002210 err_code |= ERR_ALERT | ERR_FATAL;
2211 goto out;
Emeric Brun32da3c42010-09-23 18:39:19 +02002212 }
Willy Tarreaub36487e2013-03-10 18:37:42 +01002213
2214 proto = protocol_by_family(sk->ss_family);
2215 if (!proto || !proto->connect) {
2216 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2217 file, linenum, args[0], args[1]);
2218 err_code |= ERR_ALERT | ERR_FATAL;
2219 goto out;
2220 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002221
2222 if (port1 != port2) {
2223 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2224 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002225 err_code |= ERR_ALERT | ERR_FATAL;
2226 goto out;
2227 }
2228
Willy Tarreau2aa38802013-02-20 19:20:59 +01002229 if (!port1) {
2230 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2231 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002232 err_code |= ERR_ALERT | ERR_FATAL;
2233 goto out;
2234 }
Willy Tarreau2aa38802013-02-20 19:20:59 +01002235
Emeric Brun32da3c42010-09-23 18:39:19 +02002236 newpeer->addr = *sk;
Willy Tarreaub36487e2013-03-10 18:37:42 +01002237 newpeer->proto = proto;
Willy Tarreauf7bc57c2012-10-03 00:19:48 +02002238 newpeer->xprt = &raw_sock;
Willy Tarreaud02394b2012-05-11 18:32:18 +02002239 newpeer->sock_init_arg = NULL;
Willy Tarreau26d8c592012-05-07 18:12:14 +02002240
Emeric Brun32da3c42010-09-23 18:39:19 +02002241 if (strcmp(newpeer->id, localpeer) == 0) {
2242 /* Current is local peer, it define a frontend */
2243 newpeer->local = 1;
Emeric Brunb3971ab2015-05-12 18:49:09 +02002244 peers->local = newpeer;
Emeric Brun32da3c42010-09-23 18:39:19 +02002245
2246 if (!curpeers->peers_fe) {
2247 if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) {
2248 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2249 err_code |= ERR_ALERT | ERR_ABORT;
2250 goto out;
2251 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002252
Willy Tarreau237250c2011-07-29 01:49:03 +02002253 init_new_proxy(curpeers->peers_fe);
2254 curpeers->peers_fe->parent = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02002255 curpeers->peers_fe->id = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002256 curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file);
2257 curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum;
Willy Tarreau91d96282015-03-13 15:47:26 +01002258 peers_setup_frontend(curpeers->peers_fe);
Willy Tarreau4348fad2012-09-20 16:48:07 +02002259
2260 bind_conf = bind_conf_alloc(&curpeers->peers_fe->conf.bind, file, linenum, args[2]);
2261
Willy Tarreau902636f2013-03-10 19:44:48 +01002262 if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) {
2263 if (errmsg && *errmsg) {
2264 indent_msg(&errmsg, 2);
2265 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02002266 }
2267 else
2268 Alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n",
2269 file, linenum, args[0], args[1], args[2]);
Emeric Brun32da3c42010-09-23 18:39:19 +02002270 err_code |= ERR_FATAL;
2271 goto out;
2272 }
Willy Tarreau4348fad2012-09-20 16:48:07 +02002273
2274 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
Willy Tarreauacf3bf92013-01-18 10:51:07 +01002275 l->maxaccept = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002276 l->maxconn = curpeers->peers_fe->maxconn;
2277 l->backlog = curpeers->peers_fe->backlog;
Willy Tarreau9903f0e2015-04-04 18:50:31 +02002278 l->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02002279 l->handler = process_stream;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02002280 l->analysers |= curpeers->peers_fe->fe_req_ana;
2281 l->default_target = curpeers->peers_fe->default_target;
Willy Tarreau4348fad2012-09-20 16:48:07 +02002282 l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */
2283 global.maxsock += l->maxconn;
2284 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002285 }
Willy Tarreau8b8fd562013-01-18 11:12:27 +01002286 else {
2287 Alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n",
2288 file, linenum, args[0], args[1],
2289 curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line);
2290 err_code |= ERR_FATAL;
2291 goto out;
2292 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002293 }
2294 } /* neither "peer" nor "peers" */
Willy Tarreau77e4bd12015-05-01 20:02:17 +02002295 else if (!strcmp(args[0], "disabled")) { /* disables this peers section */
2296 curpeers->state = PR_STSTOPPED;
2297 }
2298 else if (!strcmp(args[0], "enabled")) { /* enables this peers section (used to revert a disabled default) */
2299 curpeers->state = PR_STNEW;
2300 }
Emeric Brun32da3c42010-09-23 18:39:19 +02002301 else if (*args[0] != 0) {
2302 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2303 err_code |= ERR_ALERT | ERR_FATAL;
2304 goto out;
2305 }
2306
2307out:
Willy Tarreau902636f2013-03-10 19:44:48 +01002308 free(errmsg);
Emeric Brun32da3c42010-09-23 18:39:19 +02002309 return err_code;
2310}
2311
Baptiste Assmann325137d2015-04-13 23:40:55 +02002312/*
2313 * Parse a <resolvers> section.
2314 * Returns the error code, 0 if OK, or any combination of :
2315 * - ERR_ABORT: must abort ASAP
2316 * - ERR_FATAL: we can continue parsing but not start the service
2317 * - ERR_WARN: a warning has been emitted
2318 * - ERR_ALERT: an alert has been emitted
2319 * Only the two first ones can stop processing, the two others are just
2320 * indicators.
2321 */
2322int cfg_parse_resolvers(const char *file, int linenum, char **args, int kwm)
2323{
2324 static struct dns_resolvers *curr_resolvers = NULL;
2325 struct dns_nameserver *newnameserver = NULL;
2326 const char *err;
2327 int err_code = 0;
2328 char *errmsg = NULL;
2329
2330 if (strcmp(args[0], "resolvers") == 0) { /* new resolvers section */
2331 if (!*args[1]) {
2332 Alert("parsing [%s:%d] : missing name for resolvers section.\n", file, linenum);
2333 err_code |= ERR_ALERT | ERR_ABORT;
2334 goto out;
2335 }
2336
2337 err = invalid_char(args[1]);
2338 if (err) {
2339 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2340 file, linenum, *err, args[0], args[1]);
2341 err_code |= ERR_ALERT | ERR_ABORT;
2342 goto out;
2343 }
2344
2345 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
2346 /* Error if two resolvers owns the same name */
2347 if (strcmp(curr_resolvers->id, args[1]) == 0) {
2348 Alert("Parsing [%s:%d]: resolvers '%s' has same name as another resolvers (declared at %s:%d).\n",
2349 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2350 err_code |= ERR_ALERT | ERR_ABORT;
2351 }
2352 }
2353
Vincent Bernat02779b62016-04-03 13:48:43 +02002354 if ((curr_resolvers = calloc(1, sizeof(*curr_resolvers))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002355 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2356 err_code |= ERR_ALERT | ERR_ABORT;
2357 goto out;
2358 }
2359
2360 /* default values */
2361 LIST_ADDQ(&dns_resolvers, &curr_resolvers->list);
2362 curr_resolvers->conf.file = strdup(file);
2363 curr_resolvers->conf.line = linenum;
2364 curr_resolvers->id = strdup(args[1]);
2365 curr_resolvers->query_ids = EB_ROOT;
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002366 /* default hold period for nx, other, refuse and timeout is 30s */
2367 curr_resolvers->hold.nx = 30000;
2368 curr_resolvers->hold.other = 30000;
2369 curr_resolvers->hold.refused = 30000;
2370 curr_resolvers->hold.timeout = 30000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002371 /* default hold period for valid is 10s */
Baptiste Assmann4c5490a2015-07-14 21:42:49 +02002372 curr_resolvers->hold.valid = 10000;
2373 curr_resolvers->timeout.retry = 1000;
Baptiste Assmann325137d2015-04-13 23:40:55 +02002374 curr_resolvers->resolve_retries = 3;
2375 LIST_INIT(&curr_resolvers->nameserver_list);
2376 LIST_INIT(&curr_resolvers->curr_resolution);
2377 }
2378 else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
2379 struct sockaddr_storage *sk;
2380 int port1, port2;
2381 struct protocol *proto;
2382
2383 if (!*args[2]) {
2384 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2385 file, linenum, args[0]);
2386 err_code |= ERR_ALERT | ERR_FATAL;
2387 goto out;
2388 }
2389
2390 err = invalid_char(args[1]);
2391 if (err) {
2392 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2393 file, linenum, *err, args[1]);
2394 err_code |= ERR_ALERT | ERR_FATAL;
2395 goto out;
2396 }
2397
Baptiste Assmanna315c552015-11-02 22:55:49 +01002398 list_for_each_entry(newnameserver, &curr_resolvers->nameserver_list, list) {
2399 /* Error if two resolvers owns the same name */
2400 if (strcmp(newnameserver->id, args[1]) == 0) {
2401 Alert("Parsing [%s:%d]: nameserver '%s' has same name as another nameserver (declared at %s:%d).\n",
2402 file, linenum, args[1], curr_resolvers->conf.file, curr_resolvers->conf.line);
2403 err_code |= ERR_ALERT | ERR_FATAL;
2404 }
2405 }
2406
Vincent Bernat02779b62016-04-03 13:48:43 +02002407 if ((newnameserver = calloc(1, sizeof(*newnameserver))) == NULL) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002408 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2409 err_code |= ERR_ALERT | ERR_ABORT;
2410 goto out;
2411 }
2412
2413 /* the nameservers are linked backward first */
2414 LIST_ADDQ(&curr_resolvers->nameserver_list, &newnameserver->list);
2415 curr_resolvers->count_nameservers++;
2416 newnameserver->resolvers = curr_resolvers;
2417 newnameserver->conf.file = strdup(file);
2418 newnameserver->conf.line = linenum;
2419 newnameserver->id = strdup(args[1]);
2420
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002421 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002422 if (!sk) {
2423 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2424 err_code |= ERR_ALERT | ERR_FATAL;
2425 goto out;
2426 }
2427
2428 proto = protocol_by_family(sk->ss_family);
2429 if (!proto || !proto->connect) {
2430 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
2431 file, linenum, args[0], args[1]);
2432 err_code |= ERR_ALERT | ERR_FATAL;
2433 goto out;
2434 }
2435
2436 if (port1 != port2) {
2437 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2438 file, linenum, args[0], args[1], args[2]);
2439 err_code |= ERR_ALERT | ERR_FATAL;
2440 goto out;
2441 }
2442
Baptiste Assmann7f43fa92016-01-21 00:59:46 +01002443 if (!port1 && !port2) {
2444 Alert("parsing [%s:%d] : '%s %s' : no UDP port specified\n",
2445 file, linenum, args[0], args[1]);
2446 err_code |= ERR_ALERT | ERR_FATAL;
2447 goto out;
2448 }
2449
Baptiste Assmann325137d2015-04-13 23:40:55 +02002450 newnameserver->addr = *sk;
2451 }
2452 else if (strcmp(args[0], "hold") == 0) { /* hold periods */
2453 const char *res;
2454 unsigned int time;
2455
2456 if (!*args[2]) {
2457 Alert("parsing [%s:%d] : '%s' expects an <event> and a <time> as arguments.\n",
2458 file, linenum, args[0]);
2459 Alert("<event> can be either 'valid', 'nx', 'refused', 'timeout', or 'other'\n");
2460 err_code |= ERR_ALERT | ERR_FATAL;
2461 goto out;
2462 }
2463 res = parse_time_err(args[2], &time, TIME_UNIT_MS);
2464 if (res) {
2465 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2466 file, linenum, *res, args[0]);
2467 err_code |= ERR_ALERT | ERR_FATAL;
2468 goto out;
2469 }
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002470 if (strcmp(args[1], "nx") == 0)
2471 curr_resolvers->hold.nx = time;
2472 else if (strcmp(args[1], "other") == 0)
2473 curr_resolvers->hold.other = time;
2474 else if (strcmp(args[1], "refused") == 0)
2475 curr_resolvers->hold.refused = time;
2476 else if (strcmp(args[1], "timeout") == 0)
2477 curr_resolvers->hold.timeout = time;
2478 else if (strcmp(args[1], "valid") == 0)
Baptiste Assmann325137d2015-04-13 23:40:55 +02002479 curr_resolvers->hold.valid = time;
2480 else {
Baptiste Assmann987e16d2016-11-02 22:23:31 +01002481 Alert("parsing [%s:%d] : '%s' unknown <event>: '%s', expects either 'nx', 'timeout', 'valid', or 'other'.\n",
2482 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002483 err_code |= ERR_ALERT | ERR_FATAL;
2484 goto out;
2485 }
2486
2487 }
2488 else if (strcmp(args[0], "resolve_retries") == 0) {
2489 if (!*args[1]) {
2490 Alert("parsing [%s:%d] : '%s' expects <nb> as argument.\n",
2491 file, linenum, args[0]);
2492 err_code |= ERR_ALERT | ERR_FATAL;
2493 goto out;
2494 }
2495 curr_resolvers->resolve_retries = atoi(args[1]);
2496 }
2497 else if (strcmp(args[0], "timeout") == 0) {
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002498 if (!*args[1]) {
Baptiste Assmann325137d2015-04-13 23:40:55 +02002499 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments.\n",
2500 file, linenum, args[0]);
2501 err_code |= ERR_ALERT | ERR_FATAL;
2502 goto out;
2503 }
Pieter Baauw7a91a0e2016-02-13 15:51:58 +01002504 else if (strcmp(args[1], "retry") == 0) {
2505 const char *res;
2506 unsigned int timeout_retry;
2507
2508 if (!*args[2]) {
2509 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2510 file, linenum, args[0], args[1]);
2511 err_code |= ERR_ALERT | ERR_FATAL;
2512 goto out;
2513 }
2514 res = parse_time_err(args[2], &timeout_retry, TIME_UNIT_MS);
2515 if (res) {
2516 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s %s>.\n",
2517 file, linenum, *res, args[0], args[1]);
2518 err_code |= ERR_ALERT | ERR_FATAL;
2519 goto out;
2520 }
2521 curr_resolvers->timeout.retry = timeout_retry;
2522 }
2523 else {
2524 Alert("parsing [%s:%d] : '%s' expects 'retry' and <time> as arguments got '%s'.\n",
2525 file, linenum, args[0], args[1]);
Baptiste Assmann325137d2015-04-13 23:40:55 +02002526 err_code |= ERR_ALERT | ERR_FATAL;
2527 goto out;
2528 }
Baptiste Assmann325137d2015-04-13 23:40:55 +02002529 } /* neither "nameserver" nor "resolvers" */
2530 else if (*args[0] != 0) {
2531 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2532 err_code |= ERR_ALERT | ERR_FATAL;
2533 goto out;
2534 }
2535
2536 out:
2537 free(errmsg);
2538 return err_code;
2539}
Simon Horman0d16a402015-01-30 11:22:58 +09002540
2541/*
William Lallemand51097192015-04-14 16:35:22 +02002542 * Parse a line in a <listen>, <frontend> or <backend> section.
Simon Horman0d16a402015-01-30 11:22:58 +09002543 * Returns the error code, 0 if OK, or any combination of :
2544 * - ERR_ABORT: must abort ASAP
2545 * - ERR_FATAL: we can continue parsing but not start the service
2546 * - ERR_WARN: a warning has been emitted
2547 * - ERR_ALERT: an alert has been emitted
2548 * Only the two first ones can stop processing, the two others are just
2549 * indicators.
2550 */
2551int cfg_parse_mailers(const char *file, int linenum, char **args, int kwm)
2552{
2553 static struct mailers *curmailers = NULL;
2554 struct mailer *newmailer = NULL;
2555 const char *err;
2556 int err_code = 0;
2557 char *errmsg = NULL;
2558
2559 if (strcmp(args[0], "mailers") == 0) { /* new mailers section */
2560 if (!*args[1]) {
2561 Alert("parsing [%s:%d] : missing name for mailers section.\n", file, linenum);
2562 err_code |= ERR_ALERT | ERR_ABORT;
2563 goto out;
2564 }
2565
2566 err = invalid_char(args[1]);
2567 if (err) {
2568 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2569 file, linenum, *err, args[0], args[1]);
2570 err_code |= ERR_ALERT | ERR_ABORT;
2571 goto out;
2572 }
2573
2574 for (curmailers = mailers; curmailers != NULL; curmailers = curmailers->next) {
2575 /*
2576 * If there are two proxies with the same name only following
2577 * combinations are allowed:
2578 */
2579 if (strcmp(curmailers->id, args[1]) == 0) {
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002580 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 +09002581 file, linenum, args[1], curmailers->conf.file, curmailers->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002582 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman0d16a402015-01-30 11:22:58 +09002583 }
2584 }
2585
Vincent Bernat02779b62016-04-03 13:48:43 +02002586 if ((curmailers = calloc(1, sizeof(*curmailers))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002587 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2588 err_code |= ERR_ALERT | ERR_ABORT;
2589 goto out;
2590 }
2591
2592 curmailers->next = mailers;
2593 mailers = curmailers;
2594 curmailers->conf.file = strdup(file);
2595 curmailers->conf.line = linenum;
2596 curmailers->id = strdup(args[1]);
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002597 curmailers->timeout.mail = DEF_MAILALERTTIME;/* XXX: Would like to Skip to the next alert, if any, ASAP.
2598 * But need enough time so that timeouts don't occur
2599 * during tcp procssing. For now just us an arbitrary default. */
Simon Horman0d16a402015-01-30 11:22:58 +09002600 }
2601 else if (strcmp(args[0], "mailer") == 0) { /* mailer definition */
2602 struct sockaddr_storage *sk;
2603 int port1, port2;
2604 struct protocol *proto;
2605
2606 if (!*args[2]) {
2607 Alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
2608 file, linenum, args[0]);
2609 err_code |= ERR_ALERT | ERR_FATAL;
2610 goto out;
2611 }
2612
2613 err = invalid_char(args[1]);
2614 if (err) {
2615 Alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n",
2616 file, linenum, *err, args[1]);
2617 err_code |= ERR_ALERT | ERR_FATAL;
2618 goto out;
2619 }
2620
Vincent Bernat02779b62016-04-03 13:48:43 +02002621 if ((newmailer = calloc(1, sizeof(*newmailer))) == NULL) {
Simon Horman0d16a402015-01-30 11:22:58 +09002622 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
2623 err_code |= ERR_ALERT | ERR_ABORT;
2624 goto out;
2625 }
2626
2627 /* the mailers are linked backwards first */
2628 curmailers->count++;
2629 newmailer->next = curmailers->mailer_list;
2630 curmailers->mailer_list = newmailer;
2631 newmailer->mailers = curmailers;
2632 newmailer->conf.file = strdup(file);
2633 newmailer->conf.line = linenum;
2634
2635 newmailer->id = strdup(args[1]);
2636
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02002637 sk = str2sa_range(args[2], &port1, &port2, &errmsg, NULL, NULL, 1);
Simon Horman0d16a402015-01-30 11:22:58 +09002638 if (!sk) {
2639 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
2640 err_code |= ERR_ALERT | ERR_FATAL;
2641 goto out;
2642 }
2643
2644 proto = protocol_by_family(sk->ss_family);
Simon Horman0ba0e4a2015-01-30 11:23:00 +09002645 if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
2646 Alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
Simon Horman0d16a402015-01-30 11:22:58 +09002647 file, linenum, args[0], args[1]);
2648 err_code |= ERR_ALERT | ERR_FATAL;
2649 goto out;
2650 }
2651
2652 if (port1 != port2) {
2653 Alert("parsing [%s:%d] : '%s %s' : port ranges and offsets are not allowed in '%s'\n",
2654 file, linenum, args[0], args[1], args[2]);
2655 err_code |= ERR_ALERT | ERR_FATAL;
2656 goto out;
2657 }
2658
2659 if (!port1) {
2660 Alert("parsing [%s:%d] : '%s %s' : missing or invalid port in '%s'\n",
2661 file, linenum, args[0], args[1], args[2]);
2662 err_code |= ERR_ALERT | ERR_FATAL;
2663 goto out;
2664 }
2665
2666 newmailer->addr = *sk;
2667 newmailer->proto = proto;
2668 newmailer->xprt = &raw_sock;
2669 newmailer->sock_init_arg = NULL;
Pieter Baauw235fcfc2016-02-13 15:33:40 +01002670 }
2671 else if (strcmp(args[0], "timeout") == 0) {
2672 if (!*args[1]) {
2673 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments.\n",
2674 file, linenum, args[0]);
2675 err_code |= ERR_ALERT | ERR_FATAL;
2676 goto out;
2677 }
2678 else if (strcmp(args[1], "mail") == 0) {
2679 const char *res;
2680 unsigned int timeout_mail;
2681 if (!*args[2]) {
2682 Alert("parsing [%s:%d] : '%s %s' expects <time> as argument.\n",
2683 file, linenum, args[0], args[1]);
2684 err_code |= ERR_ALERT | ERR_FATAL;
2685 goto out;
2686 }
2687 res = parse_time_err(args[2], &timeout_mail, TIME_UNIT_MS);
2688 if (res) {
2689 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
2690 file, linenum, *res, args[0]);
2691 err_code |= ERR_ALERT | ERR_FATAL;
2692 goto out;
2693 }
2694 if (timeout_mail <= 0) {
2695 Alert("parsing [%s:%d] : '%s %s' expects a positive <time> argument.\n", file, linenum, args[0], args[1]);
2696 err_code |= ERR_ALERT | ERR_FATAL;
2697 goto out;
2698 }
2699 curmailers->timeout.mail = timeout_mail;
2700 } else {
2701 Alert("parsing [%s:%d] : '%s' expects 'mail' and <time> as arguments got '%s'.\n",
2702 file, linenum, args[0], args[1]);
2703 err_code |= ERR_ALERT | ERR_FATAL;
2704 goto out;
2705 }
2706 }
Simon Horman0d16a402015-01-30 11:22:58 +09002707 else if (*args[0] != 0) {
2708 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
2709 err_code |= ERR_ALERT | ERR_FATAL;
2710 goto out;
2711 }
2712
2713out:
2714 free(errmsg);
2715 return err_code;
2716}
2717
Simon Horman9dc49962015-01-30 11:22:59 +09002718static void free_email_alert(struct proxy *p)
2719{
2720 free(p->email_alert.mailers.name);
2721 p->email_alert.mailers.name = NULL;
2722 free(p->email_alert.from);
2723 p->email_alert.from = NULL;
2724 free(p->email_alert.to);
2725 p->email_alert.to = NULL;
2726 free(p->email_alert.myhostname);
2727 p->email_alert.myhostname = NULL;
2728}
2729
Willy Tarreau3842f002009-06-14 11:39:52 +02002730int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
Willy Tarreaubaaee002006-06-26 02:48:02 +02002731{
2732 static struct proxy *curproxy = NULL;
Willy Tarreaub17916e2006-10-15 15:17:57 +02002733 const char *err;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002734 char *error;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01002735 int rc;
2736 unsigned val;
Willy Tarreau93893792009-07-23 13:19:11 +02002737 int err_code = 0;
Willy Tarreau3ec18a02010-01-28 19:01:34 +01002738 struct acl_cond *cond = NULL;
William Lallemand723b73a2012-02-08 16:37:49 +01002739 struct logsrv *tmplogsrv;
Willy Tarreauf4068b62012-05-08 17:37:49 +02002740 char *errmsg = NULL;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02002741 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002742
Willy Tarreau977b8e42006-12-29 14:19:17 +01002743 if (!strcmp(args[0], "listen"))
2744 rc = PR_CAP_LISTEN;
2745 else if (!strcmp(args[0], "frontend"))
2746 rc = PR_CAP_FE | PR_CAP_RS;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02002747 else if (!strcmp(args[0], "backend"))
Willy Tarreau977b8e42006-12-29 14:19:17 +01002748 rc = PR_CAP_BE | PR_CAP_RS;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002749 else
2750 rc = PR_CAP_NONE;
2751
2752 if (rc != PR_CAP_NONE) { /* new proxy */
Willy Tarreaubaaee002006-06-26 02:48:02 +02002753 if (!*args[1]) {
2754 Alert("parsing [%s:%d] : '%s' expects an <id> argument and\n"
Ian Miell71c432e2015-08-18 19:32:08 +01002755 " optionally supports [addr1]:port1[-end1]{,[addr]:port[-end]}...\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02002756 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02002757 err_code |= ERR_ALERT | ERR_ABORT;
2758 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002759 }
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002760
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002761 err = invalid_char(args[1]);
2762 if (err) {
2763 Alert("parsing [%s:%d] : character '%c' is not permitted in '%s' name '%s'.\n",
2764 file, linenum, *err, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02002765 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01002766 }
2767
Willy Tarreau8f50b682015-05-26 11:45:02 +02002768 curproxy = (rc & PR_CAP_FE) ? proxy_fe_by_name(args[1]) : proxy_be_by_name(args[1]);
2769 if (curproxy) {
2770 Alert("Parsing [%s:%d]: %s '%s' has the same name as %s '%s' declared at %s:%d.\n",
2771 file, linenum, proxy_cap_str(rc), args[1], proxy_type_str(curproxy),
2772 curproxy->id, curproxy->conf.file, curproxy->conf.line);
Willy Tarreau911fa2e2015-05-26 10:35:50 +02002773 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki365d1cd2007-10-21 02:55:17 +02002774 }
2775
Vincent Bernat02779b62016-04-03 13:48:43 +02002776 if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02002777 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02002778 err_code |= ERR_ALERT | ERR_ABORT;
2779 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002780 }
Willy Tarreau5af24ef2009-03-15 15:23:16 +01002781
Willy Tarreau97cb7802010-01-03 20:23:58 +01002782 init_new_proxy(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002783 curproxy->next = proxy;
2784 proxy = curproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02002785 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
2786 curproxy->conf.args.line = curproxy->conf.line = linenum;
Krzysztof Oledzki85130942007-10-22 16:21:10 +02002787 curproxy->last_change = now.tv_sec;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002788 curproxy->id = strdup(args[1]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002789 curproxy->cap = rc;
Willy Tarreauf79d9502014-03-15 07:22:35 +01002790 proxy_store_name(curproxy);
Willy Tarreaubaaee002006-06-26 02:48:02 +02002791
William Lallemand6e62fb62015-04-28 16:55:23 +02002792 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
2793 if (curproxy->cap & PR_CAP_FE)
2794 Alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum);
2795 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002796 }
2797
2798 /* set default values */
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002799 memcpy(&curproxy->defsrv, &defproxy.defsrv, sizeof(curproxy->defsrv));
Willy Tarreau70160202010-04-07 16:06:40 +02002800 curproxy->defsrv.id = "default-server";
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01002801
Willy Tarreaubaaee002006-06-26 02:48:02 +02002802 curproxy->state = defproxy.state;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002803 curproxy->options = defproxy.options;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01002804 curproxy->options2 = defproxy.options2;
Willy Tarreau84b57da2009-06-14 11:10:45 +02002805 curproxy->no_options = defproxy.no_options;
2806 curproxy->no_options2 = defproxy.no_options2;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01002807 curproxy->bind_proc = defproxy.bind_proc;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02002808 curproxy->except_net = defproxy.except_net;
2809 curproxy->except_mask = defproxy.except_mask;
Maik Broemme36db02e2009-05-08 17:02:07 +02002810 curproxy->except_to = defproxy.except_to;
Maik Broemme2850cb42009-04-17 18:53:21 +02002811 curproxy->except_mask_to = defproxy.except_mask_to;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002812
Willy Tarreau79f5fe82008-08-23 08:18:21 +02002813 if (defproxy.fwdfor_hdr_len) {
2814 curproxy->fwdfor_hdr_len = defproxy.fwdfor_hdr_len;
2815 curproxy->fwdfor_hdr_name = strdup(defproxy.fwdfor_hdr_name);
2816 }
2817
Willy Tarreaub86db342009-11-30 11:50:16 +01002818 if (defproxy.orgto_hdr_len) {
2819 curproxy->orgto_hdr_len = defproxy.orgto_hdr_len;
2820 curproxy->orgto_hdr_name = strdup(defproxy.orgto_hdr_name);
2821 }
2822
Mark Lamourinec2247f02012-01-04 13:02:01 -05002823 if (defproxy.server_id_hdr_len) {
2824 curproxy->server_id_hdr_len = defproxy.server_id_hdr_len;
2825 curproxy->server_id_hdr_name = strdup(defproxy.server_id_hdr_name);
2826 }
2827
Willy Tarreau977b8e42006-12-29 14:19:17 +01002828 if (curproxy->cap & PR_CAP_FE) {
2829 curproxy->maxconn = defproxy.maxconn;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01002830 curproxy->backlog = defproxy.backlog;
Willy Tarreau13a34bd2009-05-10 18:52:49 +02002831 curproxy->fe_sps_lim = defproxy.fe_sps_lim;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002832
2833 /* initialize error relocations */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02002834 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
2835 chunk_dup(&curproxy->errmsg[rc], &defproxy.errmsg[rc]);
Willy Tarreau977b8e42006-12-29 14:19:17 +01002836
2837 curproxy->to_log = defproxy.to_log & ~LW_COOKIE & ~LW_REQHDR & ~ LW_RSPHDR;
2838 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002839
Willy Tarreau977b8e42006-12-29 14:19:17 +01002840 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreau743c1282014-11-18 15:04:29 +01002841 curproxy->lbprm.algo = defproxy.lbprm.algo;
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04002842 curproxy->lbprm.chash.balance_factor = defproxy.lbprm.chash.balance_factor;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002843 curproxy->fullconn = defproxy.fullconn;
2844 curproxy->conn_retries = defproxy.conn_retries;
Joseph Lynch726ab712015-05-11 23:25:34 -07002845 curproxy->redispatch_after = defproxy.redispatch_after;
Willy Tarreauc35362a2014-04-25 13:58:37 +02002846 curproxy->max_ka_queue = defproxy.max_ka_queue;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002847
Willy Tarreauaa2f3892010-10-22 16:15:31 +02002848 if (defproxy.check_req) {
2849 curproxy->check_req = calloc(1, defproxy.check_len);
2850 memcpy(curproxy->check_req, defproxy.check_req, defproxy.check_len);
2851 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002852 curproxy->check_len = defproxy.check_len;
Willy Tarreaubaaee002006-06-26 02:48:02 +02002853
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002854 if (defproxy.expect_str) {
2855 curproxy->expect_str = strdup(defproxy.expect_str);
2856 if (defproxy.expect_regex) {
2857 /* note: this regex is known to be valid */
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02002858 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
2859 regex_comp(defproxy.expect_str, curproxy->expect_regex, 1, 1, NULL);
Willy Tarreau1ee51a62011-08-19 20:04:17 +02002860 }
2861 }
2862
Willy Tarreau67402132012-05-31 20:40:20 +02002863 curproxy->ck_opts = defproxy.ck_opts;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002864 if (defproxy.cookie_name)
2865 curproxy->cookie_name = strdup(defproxy.cookie_name);
2866 curproxy->cookie_len = defproxy.cookie_len;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01002867 if (defproxy.cookie_domain)
2868 curproxy->cookie_domain = strdup(defproxy.cookie_domain);
Willy Tarreau01732802007-11-01 22:48:15 +01002869
Willy Tarreau31936852010-10-06 16:59:56 +02002870 if (defproxy.cookie_maxidle)
2871 curproxy->cookie_maxidle = defproxy.cookie_maxidle;
2872
2873 if (defproxy.cookie_maxlife)
2874 curproxy->cookie_maxlife = defproxy.cookie_maxlife;
2875
Emeric Brun647caf12009-06-30 17:57:00 +02002876 if (defproxy.rdp_cookie_name)
2877 curproxy->rdp_cookie_name = strdup(defproxy.rdp_cookie_name);
2878 curproxy->rdp_cookie_len = defproxy.rdp_cookie_len;
2879
Willy Tarreau01732802007-11-01 22:48:15 +01002880 if (defproxy.url_param_name)
2881 curproxy->url_param_name = strdup(defproxy.url_param_name);
2882 curproxy->url_param_len = defproxy.url_param_len;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01002883
Benoitaffb4812009-03-25 13:02:10 +01002884 if (defproxy.hh_name)
2885 curproxy->hh_name = strdup(defproxy.hh_name);
2886 curproxy->hh_len = defproxy.hh_len;
2887 curproxy->hh_match_domain = defproxy.hh_match_domain;
2888
Willy Tarreauef9a3602012-12-08 22:29:20 +01002889 if (defproxy.conn_src.iface_name)
2890 curproxy->conn_src.iface_name = strdup(defproxy.conn_src.iface_name);
2891 curproxy->conn_src.iface_len = defproxy.conn_src.iface_len;
Godbach9f048532013-04-23 15:27:57 +08002892 curproxy->conn_src.opts = defproxy.conn_src.opts;
Willy Tarreau29fbe512015-08-20 19:35:14 +02002893#if defined(CONFIG_HAP_TRANSPARENT)
Godbach9f048532013-04-23 15:27:57 +08002894 curproxy->conn_src.tproxy_addr = defproxy.conn_src.tproxy_addr;
Willy Tarreauc621d362013-04-25 17:35:22 +02002895#endif
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02002896 curproxy->load_server_state_from_file = defproxy.load_server_state_from_file;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002897 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002898
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02002899 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01002900 if (defproxy.capture_name)
2901 curproxy->capture_name = strdup(defproxy.capture_name);
2902 curproxy->capture_namelen = defproxy.capture_namelen;
2903 curproxy->capture_len = defproxy.capture_len;
Willy Tarreau0f772532006-12-23 20:51:41 +01002904 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02002905
Willy Tarreau977b8e42006-12-29 14:19:17 +01002906 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002907 curproxy->timeout.client = defproxy.timeout.client;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002908 curproxy->timeout.clientfin = defproxy.timeout.clientfin;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002909 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau036fae02008-01-06 13:24:40 +01002910 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002911 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002912 curproxy->mon_net = defproxy.mon_net;
2913 curproxy->mon_mask = defproxy.mon_mask;
2914 if (defproxy.monitor_uri)
2915 curproxy->monitor_uri = strdup(defproxy.monitor_uri);
2916 curproxy->monitor_uri_len = defproxy.monitor_uri_len;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01002917 if (defproxy.defbe.name)
2918 curproxy->defbe.name = strdup(defproxy.defbe.name);
Willy Tarreau99a7ca22012-05-31 19:39:23 +02002919
2920 /* get either a pointer to the logformat string or a copy of it */
Willy Tarreau62a61232013-04-12 18:13:46 +02002921 curproxy->conf.logformat_string = defproxy.conf.logformat_string;
2922 if (curproxy->conf.logformat_string &&
2923 curproxy->conf.logformat_string != default_http_log_format &&
2924 curproxy->conf.logformat_string != default_tcp_log_format &&
2925 curproxy->conf.logformat_string != clf_http_log_format)
2926 curproxy->conf.logformat_string = strdup(curproxy->conf.logformat_string);
2927
2928 if (defproxy.conf.lfs_file) {
2929 curproxy->conf.lfs_file = strdup(defproxy.conf.lfs_file);
2930 curproxy->conf.lfs_line = defproxy.conf.lfs_line;
2931 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02002932
2933 /* get either a pointer to the logformat string for RFC5424 structured-data or a copy of it */
2934 curproxy->conf.logformat_sd_string = defproxy.conf.logformat_sd_string;
2935 if (curproxy->conf.logformat_sd_string &&
2936 curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
2937 curproxy->conf.logformat_sd_string = strdup(curproxy->conf.logformat_sd_string);
2938
2939 if (defproxy.conf.lfsd_file) {
2940 curproxy->conf.lfsd_file = strdup(defproxy.conf.lfsd_file);
2941 curproxy->conf.lfsd_line = defproxy.conf.lfsd_line;
2942 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01002943 }
2944
2945 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaud7c30f92007-12-03 01:38:36 +01002946 curproxy->timeout.connect = defproxy.timeout.connect;
2947 curproxy->timeout.server = defproxy.timeout.server;
Simone Gotti1b48cc92014-06-11 12:25:28 +02002948 curproxy->timeout.serverfin = defproxy.timeout.serverfin;
Krzysztof Piotr Oledzki5259dfe2008-01-21 01:54:06 +01002949 curproxy->timeout.check = defproxy.timeout.check;
Willy Tarreau1fa31262007-12-03 00:36:16 +01002950 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau51c9bde2008-01-06 13:40:03 +01002951 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreaucd7afc02009-07-12 10:03:17 +02002952 curproxy->timeout.httpreq = defproxy.timeout.httpreq;
Willy Tarreaub16a5742010-01-10 14:46:16 +01002953 curproxy->timeout.httpka = defproxy.timeout.httpka;
Willy Tarreauce887fd2012-05-12 12:50:00 +02002954 curproxy->timeout.tunnel = defproxy.timeout.tunnel;
Willy Tarreauef9a3602012-12-08 22:29:20 +01002955 curproxy->conn_src.source_addr = defproxy.conn_src.source_addr;
Willy Tarreau977b8e42006-12-29 14:19:17 +01002956 }
2957
Willy Tarreaubaaee002006-06-26 02:48:02 +02002958 curproxy->mode = defproxy.mode;
Willy Tarreaued2119c2014-04-24 22:10:39 +02002959 curproxy->uri_auth = defproxy.uri_auth; /* for stats */
William Lallemand0f99e342011-10-12 17:50:54 +02002960
2961 /* copy default logsrvs to curproxy */
William Lallemand723b73a2012-02-08 16:37:49 +01002962 list_for_each_entry(tmplogsrv, &defproxy.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02002963 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01002964 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02002965 LIST_INIT(&node->list);
2966 LIST_ADDQ(&curproxy->logsrvs, &node->list);
2967 }
2968
Willy Tarreau62a61232013-04-12 18:13:46 +02002969 curproxy->conf.uniqueid_format_string = defproxy.conf.uniqueid_format_string;
2970 if (curproxy->conf.uniqueid_format_string)
2971 curproxy->conf.uniqueid_format_string = strdup(curproxy->conf.uniqueid_format_string);
2972
Dragan Dosen43885c72015-10-01 13:18:13 +02002973 chunk_dup(&curproxy->log_tag, &defproxy.log_tag);
Willy Tarreau094af4e2015-01-07 15:03:42 +01002974
Willy Tarreau62a61232013-04-12 18:13:46 +02002975 if (defproxy.conf.uif_file) {
2976 curproxy->conf.uif_file = strdup(defproxy.conf.uif_file);
2977 curproxy->conf.uif_line = defproxy.conf.uif_line;
2978 }
William Lallemanda73203e2012-03-12 12:48:57 +01002979
2980 /* copy default header unique id */
2981 if (defproxy.header_unique_id)
2982 curproxy->header_unique_id = strdup(defproxy.header_unique_id);
2983
William Lallemand82fe75c2012-10-23 10:25:10 +02002984 /* default compression options */
2985 if (defproxy.comp != NULL) {
2986 curproxy->comp = calloc(1, sizeof(struct comp));
2987 curproxy->comp->algos = defproxy.comp->algos;
2988 curproxy->comp->types = defproxy.comp->types;
2989 }
2990
Willy Tarreaubaaee002006-06-26 02:48:02 +02002991 curproxy->grace = defproxy.grace;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02002992 curproxy->conf.used_listener_id = EB_ROOT;
2993 curproxy->conf.used_server_id = EB_ROOT;
Willy Tarreau1c47f852006-07-09 08:22:27 +02002994
Simon Horman98637e52014-06-20 12:30:16 +09002995 if (defproxy.check_path)
2996 curproxy->check_path = strdup(defproxy.check_path);
2997 if (defproxy.check_command)
2998 curproxy->check_command = strdup(defproxy.check_command);
2999
Simon Horman9dc49962015-01-30 11:22:59 +09003000 if (defproxy.email_alert.mailers.name)
3001 curproxy->email_alert.mailers.name = strdup(defproxy.email_alert.mailers.name);
3002 if (defproxy.email_alert.from)
3003 curproxy->email_alert.from = strdup(defproxy.email_alert.from);
3004 if (defproxy.email_alert.to)
3005 curproxy->email_alert.to = strdup(defproxy.email_alert.to);
3006 if (defproxy.email_alert.myhostname)
3007 curproxy->email_alert.myhostname = strdup(defproxy.email_alert.myhostname);
Simon Horman64e34162015-02-06 11:11:57 +09003008 curproxy->email_alert.level = defproxy.email_alert.level;
Cyril Bonté7e084702015-12-04 03:07:06 +01003009 curproxy->email_alert.set = defproxy.email_alert.set;
Simon Horman9dc49962015-01-30 11:22:59 +09003010
Willy Tarreau93893792009-07-23 13:19:11 +02003011 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003012 }
3013 else if (!strcmp(args[0], "defaults")) { /* use this one to assign default values */
3014 /* some variables may have already been initialized earlier */
Willy Tarreau5fdfb912007-01-01 23:11:07 +01003015 /* FIXME-20070101: we should do this too at the end of the
3016 * config parsing to free all default values.
3017 */
William Lallemand6e62fb62015-04-28 16:55:23 +02003018 if (alertif_too_many_args(1, file, linenum, args, &err_code)) {
3019 err_code |= ERR_ABORT;
3020 goto out;
3021 }
3022
Willy Tarreaua534fea2008-08-03 12:19:50 +02003023 free(defproxy.check_req);
Simon Horman98637e52014-06-20 12:30:16 +09003024 free(defproxy.check_command);
3025 free(defproxy.check_path);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003026 free(defproxy.cookie_name);
Emeric Brun647caf12009-06-30 17:57:00 +02003027 free(defproxy.rdp_cookie_name);
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003028 free(defproxy.cookie_domain);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003029 free(defproxy.url_param_name);
Benoitaffb4812009-03-25 13:02:10 +01003030 free(defproxy.hh_name);
Willy Tarreaua534fea2008-08-03 12:19:50 +02003031 free(defproxy.capture_name);
3032 free(defproxy.monitor_uri);
3033 free(defproxy.defbe.name);
Willy Tarreauef9a3602012-12-08 22:29:20 +01003034 free(defproxy.conn_src.iface_name);
Willy Tarreau79f5fe82008-08-23 08:18:21 +02003035 free(defproxy.fwdfor_hdr_name);
3036 defproxy.fwdfor_hdr_len = 0;
Willy Tarreaub86db342009-11-30 11:50:16 +01003037 free(defproxy.orgto_hdr_name);
3038 defproxy.orgto_hdr_len = 0;
Mark Lamourinec2247f02012-01-04 13:02:01 -05003039 free(defproxy.server_id_hdr_name);
3040 defproxy.server_id_hdr_len = 0;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02003041 free(defproxy.expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003042 if (defproxy.expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02003043 regex_free(defproxy.expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02003044 free(defproxy.expect_regex);
3045 defproxy.expect_regex = NULL;
3046 }
Willy Tarreau0f772532006-12-23 20:51:41 +01003047
Willy Tarreau62a61232013-04-12 18:13:46 +02003048 if (defproxy.conf.logformat_string != default_http_log_format &&
3049 defproxy.conf.logformat_string != default_tcp_log_format &&
3050 defproxy.conf.logformat_string != clf_http_log_format)
3051 free(defproxy.conf.logformat_string);
Willy Tarreau196729e2012-05-31 19:30:26 +02003052
Willy Tarreau62a61232013-04-12 18:13:46 +02003053 free(defproxy.conf.uniqueid_format_string);
3054 free(defproxy.conf.lfs_file);
3055 free(defproxy.conf.uif_file);
Dragan Dosen43885c72015-10-01 13:18:13 +02003056 chunk_destroy(&defproxy.log_tag);
Simon Horman9dc49962015-01-30 11:22:59 +09003057 free_email_alert(&defproxy);
Willy Tarreau196729e2012-05-31 19:30:26 +02003058
Dragan Dosen0b85ece2015-09-25 19:17:44 +02003059 if (defproxy.conf.logformat_sd_string != default_rfc5424_sd_log_format)
3060 free(defproxy.conf.logformat_sd_string);
3061 free(defproxy.conf.lfsd_file);
3062
Willy Tarreaua534fea2008-08-03 12:19:50 +02003063 for (rc = 0; rc < HTTP_ERR_SIZE; rc++)
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02003064 chunk_destroy(&defproxy.errmsg[rc]);
Willy Tarreau0f772532006-12-23 20:51:41 +01003065
Willy Tarreaubaaee002006-06-26 02:48:02 +02003066 /* we cannot free uri_auth because it might already be used */
3067 init_default_instance();
3068 curproxy = &defproxy;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003069 curproxy->conf.args.file = curproxy->conf.file = strdup(file);
3070 curproxy->conf.args.line = curproxy->conf.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003071 defproxy.cap = PR_CAP_LISTEN; /* all caps for now */
Willy Tarreau93893792009-07-23 13:19:11 +02003072 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003073 }
3074 else if (curproxy == NULL) {
3075 Alert("parsing [%s:%d] : 'listen' or 'defaults' expected.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003076 err_code |= ERR_ALERT | ERR_FATAL;
3077 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003078 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02003079
3080 /* update the current file and line being parsed */
3081 curproxy->conf.args.file = curproxy->conf.file;
3082 curproxy->conf.args.line = linenum;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003083
3084 /* Now let's parse the proxy-specific keywords */
Willy Tarreau272adea2014-03-31 10:39:59 +02003085 if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server")) {
3086 err_code |= parse_server(file, linenum, args, curproxy, &defproxy);
3087 if (err_code & ERR_FATAL)
3088 goto out;
3089 }
3090 else if (!strcmp(args[0], "bind")) { /* new listen addresses */
Willy Tarreau4348fad2012-09-20 16:48:07 +02003091 struct listener *l;
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003092 int cur_arg;
3093
Willy Tarreaubaaee002006-06-26 02:48:02 +02003094 if (curproxy == &defproxy) {
3095 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003096 err_code |= ERR_ALERT | ERR_FATAL;
3097 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003098 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003099 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003100 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003101
Willy Tarreau24709282013-03-10 21:32:12 +01003102 if (!*(args[1])) {
Willy Tarreaud55c3fe2010-11-09 09:50:37 +01003103 Alert("parsing [%s:%d] : '%s' expects {<path>|[addr1]:port1[-end1]}{,[addr]:port[-end]}... as arguments.\n",
Willy Tarreaubaaee002006-06-26 02:48:02 +02003104 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003105 err_code |= ERR_ALERT | ERR_FATAL;
3106 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003107 }
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003108
Willy Tarreau2a65ff02012-09-13 17:54:29 +02003109 bind_conf = bind_conf_alloc(&curproxy->conf.bind, file, linenum, args[1]);
Willy Tarreau8dc21fa2013-01-24 15:17:20 +01003110
3111 /* use default settings for unix sockets */
3112 bind_conf->ux.uid = global.unix_bind.ux.uid;
3113 bind_conf->ux.gid = global.unix_bind.ux.gid;
3114 bind_conf->ux.mode = global.unix_bind.ux.mode;
Willy Tarreau8a956912010-10-15 14:27:08 +02003115
3116 /* NOTE: the following line might create several listeners if there
3117 * are comma-separated IPs or port ranges. So all further processing
3118 * will have to be applied to all listeners created after last_listen.
3119 */
Willy Tarreau902636f2013-03-10 19:44:48 +01003120 if (!str2listener(args[1], curproxy, bind_conf, file, linenum, &errmsg)) {
3121 if (errmsg && *errmsg) {
3122 indent_msg(&errmsg, 2);
3123 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreau4fbb2282012-09-20 20:01:39 +02003124 }
3125 else
3126 Alert("parsing [%s:%d] : '%s' : error encountered while parsing listening address '%s'.\n",
3127 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003128 err_code |= ERR_ALERT | ERR_FATAL;
3129 goto out;
3130 }
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003131
Willy Tarreau4348fad2012-09-20 16:48:07 +02003132 list_for_each_entry(l, &bind_conf->listeners, by_bind) {
3133 /* Set default global rights and owner for unix bind */
Willy Tarreauc8b11092011-02-16 11:08:57 +01003134 global.maxsock++;
Willy Tarreau90a570f2009-10-04 20:54:54 +02003135 }
3136
Willy Tarreau5e6e2042009-02-04 17:19:29 +01003137 cur_arg = 2;
3138 while (*(args[cur_arg])) {
Willy Tarreau8638f482012-09-18 18:01:17 +02003139 static int bind_dumped;
Willy Tarreau26982662012-09-12 23:17:10 +02003140 struct bind_kw *kw;
Willy Tarreau8638f482012-09-18 18:01:17 +02003141 char *err;
3142
Willy Tarreau26982662012-09-12 23:17:10 +02003143 kw = bind_find_kw(args[cur_arg]);
3144 if (kw) {
3145 char *err = NULL;
3146 int code;
3147
3148 if (!kw->parse) {
Willy Tarreaudda322d2012-09-18 16:34:09 +02003149 Alert("parsing [%s:%d] : '%s %s' : '%s' option is not implemented in this version (check build options).\n",
3150 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003151 cur_arg += 1 + kw->skip ;
3152 err_code |= ERR_ALERT | ERR_FATAL;
3153 goto out;
3154 }
3155
Willy Tarreau4348fad2012-09-20 16:48:07 +02003156 code = kw->parse(args, cur_arg, curproxy, bind_conf, &err);
Willy Tarreau26982662012-09-12 23:17:10 +02003157 err_code |= code;
3158
3159 if (code) {
3160 if (err && *err) {
3161 indent_msg(&err, 2);
Willy Tarreaudda322d2012-09-18 16:34:09 +02003162 Alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], err);
Willy Tarreau26982662012-09-12 23:17:10 +02003163 }
3164 else
Willy Tarreaudda322d2012-09-18 16:34:09 +02003165 Alert("parsing [%s:%d] : '%s %s' : error encountered while processing '%s'.\n",
3166 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau26982662012-09-12 23:17:10 +02003167 if (code & ERR_FATAL) {
3168 free(err);
3169 cur_arg += 1 + kw->skip;
3170 goto out;
3171 }
3172 }
3173 free(err);
3174 cur_arg += 1 + kw->skip;
3175 continue;
3176 }
3177
Willy Tarreau8638f482012-09-18 18:01:17 +02003178 err = NULL;
3179 if (!bind_dumped) {
3180 bind_dump_kws(&err);
3181 indent_msg(&err, 4);
3182 bind_dumped = 1;
3183 }
3184
3185 Alert("parsing [%s:%d] : '%s %s' unknown keyword '%s'.%s%s\n",
3186 file, linenum, args[0], args[1], args[cur_arg],
3187 err ? " Registered keywords :" : "", err ? err : "");
3188 free(err);
3189
Willy Tarreau93893792009-07-23 13:19:11 +02003190 err_code |= ERR_ALERT | ERR_FATAL;
3191 goto out;
Willy Tarreaub1e52e82008-01-13 14:49:51 +01003192 }
Willy Tarreau93893792009-07-23 13:19:11 +02003193 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003194 }
3195 else if (!strcmp(args[0], "monitor-net")) { /* set the range of IPs to ignore */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01003196 if (!*args[1] || !str2net(args[1], 1, &curproxy->mon_net, &curproxy->mon_mask)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003197 Alert("parsing [%s:%d] : '%s' expects address[/mask].\n",
3198 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003199 err_code |= ERR_ALERT | ERR_FATAL;
3200 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003201 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01003202 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003203 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003204
Willy Tarreaubaaee002006-06-26 02:48:02 +02003205 /* flush useless bits */
3206 curproxy->mon_net.s_addr &= curproxy->mon_mask.s_addr;
Willy Tarreau93893792009-07-23 13:19:11 +02003207 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003208 }
Willy Tarreau1c47f852006-07-09 08:22:27 +02003209 else if (!strcmp(args[0], "monitor-uri")) { /* set the URI to intercept */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003210 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003211 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003212
William Lallemanddf1425a2015-04-28 20:17:49 +02003213 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3214 goto out;
3215
Willy Tarreau1c47f852006-07-09 08:22:27 +02003216 if (!*args[1]) {
3217 Alert("parsing [%s:%d] : '%s' expects an URI.\n",
3218 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003219 err_code |= ERR_ALERT | ERR_FATAL;
3220 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003221 }
3222
Willy Tarreaua534fea2008-08-03 12:19:50 +02003223 free(curproxy->monitor_uri);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003224 curproxy->monitor_uri_len = strlen(args[1]);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003225 curproxy->monitor_uri = calloc(1, curproxy->monitor_uri_len + 1);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +01003226 memcpy(curproxy->monitor_uri, args[1], curproxy->monitor_uri_len);
Willy Tarreau1c47f852006-07-09 08:22:27 +02003227 curproxy->monitor_uri[curproxy->monitor_uri_len] = '\0';
3228
Willy Tarreau93893792009-07-23 13:19:11 +02003229 goto out;
Willy Tarreau1c47f852006-07-09 08:22:27 +02003230 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003231 else if (!strcmp(args[0], "mode")) { /* sets the proxy mode */
William Lallemanddf1425a2015-04-28 20:17:49 +02003232 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3233 goto out;
3234
Willy Tarreaubaaee002006-06-26 02:48:02 +02003235 if (!strcmp(args[1], "http")) curproxy->mode = PR_MODE_HTTP;
3236 else if (!strcmp(args[1], "tcp")) curproxy->mode = PR_MODE_TCP;
3237 else if (!strcmp(args[1], "health")) curproxy->mode = PR_MODE_HEALTH;
3238 else {
3239 Alert("parsing [%s:%d] : unknown proxy mode '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003240 err_code |= ERR_ALERT | ERR_FATAL;
3241 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003242 }
3243 }
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003244 else if (!strcmp(args[0], "id")) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003245 struct eb32_node *node;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003246
3247 if (curproxy == &defproxy) {
3248 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3249 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003250 err_code |= ERR_ALERT | ERR_FATAL;
3251 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003252 }
3253
William Lallemanddf1425a2015-04-28 20:17:49 +02003254 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3255 goto out;
3256
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003257 if (!*args[1]) {
3258 Alert("parsing [%s:%d]: '%s' expects an integer argument.\n",
3259 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003260 err_code |= ERR_ALERT | ERR_FATAL;
3261 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003262 }
3263
3264 curproxy->uuid = atol(args[1]);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003265 curproxy->conf.id.key = curproxy->uuid;
Willy Tarreau0d1fdf72015-05-27 16:44:02 +02003266 curproxy->options |= PR_O_FORCED_ID;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003267
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003268 if (curproxy->uuid <= 0) {
3269 Alert("parsing [%s:%d]: custom id has to be > 0.\n",
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003270 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003271 err_code |= ERR_ALERT | ERR_FATAL;
3272 goto out;
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003273 }
3274
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02003275 node = eb32_lookup(&used_proxy_id, curproxy->uuid);
3276 if (node) {
3277 struct proxy *target = container_of(node, struct proxy, conf.id);
3278 Alert("parsing [%s:%d]: %s %s reuses same custom id as %s %s (declared at %s:%d).\n",
3279 file, linenum, proxy_type_str(curproxy), curproxy->id,
3280 proxy_type_str(target), target->id, target->conf.file, target->conf.line);
3281 err_code |= ERR_ALERT | ERR_FATAL;
3282 goto out;
3283 }
3284 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Krzysztof Piotr Oledzkif58a9622008-02-23 01:19:10 +01003285 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003286 else if (!strcmp(args[0], "description")) {
3287 int i, len=0;
3288 char *d;
3289
Cyril Bonté99ed3272010-01-24 23:29:44 +01003290 if (curproxy == &defproxy) {
3291 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n",
3292 file, linenum, args[0]);
3293 err_code |= ERR_ALERT | ERR_FATAL;
3294 goto out;
3295 }
3296
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003297 if (!*args[1]) {
3298 Alert("parsing [%s:%d]: '%s' expects a string argument.\n",
3299 file, linenum, args[0]);
3300 return -1;
3301 }
3302
Willy Tarreau348acfe2014-04-14 15:00:39 +02003303 for (i = 1; *args[i]; i++)
3304 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003305
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02003306 d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003307 curproxy->desc = d;
3308
Willy Tarreau348acfe2014-04-14 15:00:39 +02003309 d += snprintf(d, curproxy->desc + len - d, "%s", args[1]);
3310 for (i = 2; *args[i]; i++)
3311 d += snprintf(d, curproxy->desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02003312
3313 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003314 else if (!strcmp(args[0], "disabled")) { /* disables this proxy */
William Lallemanddf1425a2015-04-28 20:17:49 +02003315 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3316 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003317 curproxy->state = PR_STSTOPPED;
3318 }
3319 else if (!strcmp(args[0], "enabled")) { /* enables this proxy (used to revert a disabled default) */
William Lallemanddf1425a2015-04-28 20:17:49 +02003320 if (alertif_too_many_args(0, file, linenum, args, &err_code))
3321 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003322 curproxy->state = PR_STNEW;
3323 }
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003324 else if (!strcmp(args[0], "bind-process")) { /* enable this proxy only on some processes */
3325 int cur_arg = 1;
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003326 unsigned long set = 0;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003327
3328 while (*args[cur_arg]) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003329 unsigned int low, high;
3330
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003331 if (strcmp(args[cur_arg], "all") == 0) {
3332 set = 0;
3333 break;
3334 }
3335 else if (strcmp(args[cur_arg], "odd") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003336 set |= ~0UL/3UL; /* 0x555....555 */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003337 }
3338 else if (strcmp(args[cur_arg], "even") == 0) {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003339 set |= (~0UL/3UL) << 1; /* 0xAAA...AAA */
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003340 }
Willy Tarreau83d84cf2012-11-22 01:04:31 +01003341 else if (isdigit((int)*args[cur_arg])) {
Willy Tarreau110ecc12012-11-15 17:50:01 +01003342 char *dash = strchr(args[cur_arg], '-');
3343
3344 low = high = str2uic(args[cur_arg]);
3345 if (dash)
3346 high = str2uic(dash + 1);
3347
3348 if (high < low) {
3349 unsigned int swap = low;
3350 low = high;
3351 high = swap;
3352 }
3353
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003354 if (low < 1 || high > LONGBITS) {
3355 Alert("parsing [%s:%d]: %s supports process numbers from 1 to %d.\n",
3356 file, linenum, args[0], LONGBITS);
Willy Tarreau93893792009-07-23 13:19:11 +02003357 err_code |= ERR_ALERT | ERR_FATAL;
3358 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003359 }
Willy Tarreau110ecc12012-11-15 17:50:01 +01003360 while (low <= high)
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003361 set |= 1UL << (low++ - 1);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003362 }
3363 else {
Willy Tarreaua9db57e2013-01-18 11:29:29 +01003364 Alert("parsing [%s:%d]: %s expects 'all', 'odd', 'even', or a list of process ranges with numbers from 1 to %d.\n",
3365 file, linenum, args[0], LONGBITS);
Willy Tarreau110ecc12012-11-15 17:50:01 +01003366 err_code |= ERR_ALERT | ERR_FATAL;
3367 goto out;
Willy Tarreau0b9c02c2009-02-04 22:05:05 +01003368 }
3369 cur_arg++;
3370 }
3371 curproxy->bind_proc = set;
3372 }
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003373 else if (!strcmp(args[0], "acl")) { /* add an ACL */
Willy Tarreaub099aca2008-10-12 17:26:37 +02003374 if (curproxy == &defproxy) {
3375 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003376 err_code |= ERR_ALERT | ERR_FATAL;
3377 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003378 }
3379
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003380 err = invalid_char(args[1]);
3381 if (err) {
3382 Alert("parsing [%s:%d] : character '%c' is not permitted in acl name '%s'.\n",
3383 file, linenum, *err, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003384 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2e74c3f2007-12-02 18:45:09 +01003385 }
3386
Thierry FOURNIER0d6ba512014-02-11 03:31:34 +01003387 if (parse_acl((const char **)args + 1, &curproxy->acl, &errmsg, &curproxy->conf.args, file, linenum) == NULL) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02003388 Alert("parsing [%s:%d] : error detected while parsing ACL '%s' : %s.\n",
3389 file, linenum, args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003390 err_code |= ERR_ALERT | ERR_FATAL;
3391 goto out;
Willy Tarreaueb0c6142007-05-07 00:53:22 +02003392 }
3393 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003394 else if (!strcmp(args[0], "cookie")) { /* cookie name */
3395 int cur_arg;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003396
Willy Tarreau977b8e42006-12-29 14:19:17 +01003397 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003398 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003399
Willy Tarreaubaaee002006-06-26 02:48:02 +02003400 if (*(args[1]) == 0) {
3401 Alert("parsing [%s:%d] : '%s' expects <cookie_name> as argument.\n",
3402 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003403 err_code |= ERR_ALERT | ERR_FATAL;
3404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003405 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003406
Willy Tarreau67402132012-05-31 20:40:20 +02003407 curproxy->ck_opts = 0;
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003408 curproxy->cookie_maxidle = curproxy->cookie_maxlife = 0;
Willy Tarreau4d187ac2009-12-03 23:13:06 +01003409 free(curproxy->cookie_domain); curproxy->cookie_domain = NULL;
Willy Tarreaua534fea2008-08-03 12:19:50 +02003410 free(curproxy->cookie_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003411 curproxy->cookie_name = strdup(args[1]);
3412 curproxy->cookie_len = strlen(curproxy->cookie_name);
Willy Tarreauc63d4bb2010-10-23 11:37:27 +02003413
Willy Tarreaubaaee002006-06-26 02:48:02 +02003414 cur_arg = 2;
3415 while (*(args[cur_arg])) {
3416 if (!strcmp(args[cur_arg], "rewrite")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003417 curproxy->ck_opts |= PR_CK_RW;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003418 }
3419 else if (!strcmp(args[cur_arg], "indirect")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003420 curproxy->ck_opts |= PR_CK_IND;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003421 }
3422 else if (!strcmp(args[cur_arg], "insert")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003423 curproxy->ck_opts |= PR_CK_INS;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003424 }
3425 else if (!strcmp(args[cur_arg], "nocache")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003426 curproxy->ck_opts |= PR_CK_NOC;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003427 }
3428 else if (!strcmp(args[cur_arg], "postonly")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003429 curproxy->ck_opts |= PR_CK_POST;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003430 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003431 else if (!strcmp(args[cur_arg], "preserve")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003432 curproxy->ck_opts |= PR_CK_PSV;
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003433 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003434 else if (!strcmp(args[cur_arg], "prefix")) {
Willy Tarreau67402132012-05-31 20:40:20 +02003435 curproxy->ck_opts |= PR_CK_PFX;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003436 }
Willy Tarreau4992dd22012-05-31 21:02:17 +02003437 else if (!strcmp(args[cur_arg], "httponly")) {
3438 curproxy->ck_opts |= PR_CK_HTTPONLY;
3439 }
3440 else if (!strcmp(args[cur_arg], "secure")) {
3441 curproxy->ck_opts |= PR_CK_SECURE;
3442 }
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003443 else if (!strcmp(args[cur_arg], "domain")) {
3444 if (!*args[cur_arg + 1]) {
3445 Alert("parsing [%s:%d]: '%s' expects <domain> as argument.\n",
3446 file, linenum, args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02003447 err_code |= ERR_ALERT | ERR_FATAL;
3448 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003449 }
3450
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003451 if (*args[cur_arg + 1] != '.' || !strchr(args[cur_arg + 1] + 1, '.')) {
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003452 /* rfc2109, 4.3.2 Rejecting Cookies */
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003453 Warning("parsing [%s:%d]: domain '%s' contains no embedded"
3454 " dots nor does not start with a dot."
3455 " RFC forbids it, this configuration may not work properly.\n",
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003456 file, linenum, args[cur_arg + 1]);
Krzysztof Piotr Oledzki1a8bea92009-12-15 23:40:47 +01003457 err_code |= ERR_WARN;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003458 }
3459
3460 err = invalid_domainchar(args[cur_arg + 1]);
3461 if (err) {
3462 Alert("parsing [%s:%d]: character '%c' is not permitted in domain name '%s'.\n",
3463 file, linenum, *err, args[cur_arg + 1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003464 err_code |= ERR_ALERT | ERR_FATAL;
3465 goto out;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003466 }
3467
Willy Tarreau68a897b2009-12-03 23:28:34 +01003468 if (!curproxy->cookie_domain) {
3469 curproxy->cookie_domain = strdup(args[cur_arg + 1]);
3470 } else {
3471 /* one domain was already specified, add another one by
3472 * building the string which will be returned along with
3473 * the cookie.
3474 */
3475 char *new_ptr;
3476 int new_len = strlen(curproxy->cookie_domain) +
3477 strlen("; domain=") + strlen(args[cur_arg + 1]) + 1;
3478 new_ptr = malloc(new_len);
3479 snprintf(new_ptr, new_len, "%s; domain=%s", curproxy->cookie_domain, args[cur_arg+1]);
3480 free(curproxy->cookie_domain);
3481 curproxy->cookie_domain = new_ptr;
3482 }
Willy Tarreau31936852010-10-06 16:59:56 +02003483 cur_arg++;
3484 }
3485 else if (!strcmp(args[cur_arg], "maxidle")) {
3486 unsigned int maxidle;
3487 const char *res;
3488
3489 if (!*args[cur_arg + 1]) {
3490 Alert("parsing [%s:%d]: '%s' expects <idletime> in seconds as argument.\n",
3491 file, linenum, args[cur_arg]);
3492 err_code |= ERR_ALERT | ERR_FATAL;
3493 goto out;
3494 }
3495
3496 res = parse_time_err(args[cur_arg + 1], &maxidle, TIME_UNIT_S);
3497 if (res) {
3498 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3499 file, linenum, *res, args[cur_arg]);
3500 err_code |= ERR_ALERT | ERR_FATAL;
3501 goto out;
3502 }
3503 curproxy->cookie_maxidle = maxidle;
3504 cur_arg++;
3505 }
3506 else if (!strcmp(args[cur_arg], "maxlife")) {
3507 unsigned int maxlife;
3508 const char *res;
3509
3510 if (!*args[cur_arg + 1]) {
3511 Alert("parsing [%s:%d]: '%s' expects <lifetime> in seconds as argument.\n",
3512 file, linenum, args[cur_arg]);
3513 err_code |= ERR_ALERT | ERR_FATAL;
3514 goto out;
3515 }
3516
3517 res = parse_time_err(args[cur_arg + 1], &maxlife, TIME_UNIT_S);
3518 if (res) {
3519 Alert("parsing [%s:%d]: unexpected character '%c' in argument to <%s>.\n",
3520 file, linenum, *res, args[cur_arg]);
3521 err_code |= ERR_ALERT | ERR_FATAL;
3522 goto out;
3523 }
3524 curproxy->cookie_maxlife = maxlife;
Krzysztof Piotr Oledzkiefe3b6f2008-05-23 23:49:32 +02003525 cur_arg++;
3526 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003527 else {
Willy Tarreau31936852010-10-06 16:59:56 +02003528 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 +02003529 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003530 err_code |= ERR_ALERT | ERR_FATAL;
3531 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003532 }
3533 cur_arg++;
3534 }
Willy Tarreau67402132012-05-31 20:40:20 +02003535 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_IND))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003536 Alert("parsing [%s:%d] : cookie 'rewrite' and 'indirect' modes are incompatible.\n",
3537 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003538 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003539 }
3540
Willy Tarreau67402132012-05-31 20:40:20 +02003541 if (!POWEROF2(curproxy->ck_opts & (PR_CK_RW|PR_CK_INS|PR_CK_PFX))) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02003542 Alert("parsing [%s:%d] : cookie 'rewrite', 'insert' and 'prefix' modes are incompatible.\n",
3543 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003544 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003545 }
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003546
Willy Tarreau67402132012-05-31 20:40:20 +02003547 if ((curproxy->ck_opts & (PR_CK_PSV | PR_CK_INS | PR_CK_IND)) == PR_CK_PSV) {
Willy Tarreauba4c5be2010-10-23 12:46:42 +02003548 Alert("parsing [%s:%d] : cookie 'preserve' requires at least 'insert' or 'indirect'.\n",
3549 file, linenum);
3550 err_code |= ERR_ALERT | ERR_FATAL;
3551 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003552 }/* end else if (!strcmp(args[0], "cookie")) */
Simon Horman9dc49962015-01-30 11:22:59 +09003553 else if (!strcmp(args[0], "email-alert")) {
3554 if (*(args[1]) == 0) {
3555 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3556 file, linenum, args[0]);
3557 err_code |= ERR_ALERT | ERR_FATAL;
3558 goto out;
3559 }
3560
3561 if (!strcmp(args[1], "from")) {
3562 if (*(args[1]) == 0) {
3563 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3564 file, linenum, args[1]);
3565 err_code |= ERR_ALERT | ERR_FATAL;
3566 goto out;
3567 }
3568 free(curproxy->email_alert.from);
3569 curproxy->email_alert.from = strdup(args[2]);
3570 }
3571 else if (!strcmp(args[1], "mailers")) {
3572 if (*(args[1]) == 0) {
3573 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3574 file, linenum, args[1]);
3575 err_code |= ERR_ALERT | ERR_FATAL;
3576 goto out;
3577 }
3578 free(curproxy->email_alert.mailers.name);
3579 curproxy->email_alert.mailers.name = strdup(args[2]);
3580 }
3581 else if (!strcmp(args[1], "myhostname")) {
3582 if (*(args[1]) == 0) {
3583 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3584 file, linenum, args[1]);
3585 err_code |= ERR_ALERT | ERR_FATAL;
3586 goto out;
3587 }
3588 free(curproxy->email_alert.myhostname);
3589 curproxy->email_alert.myhostname = strdup(args[2]);
3590 }
Simon Horman64e34162015-02-06 11:11:57 +09003591 else if (!strcmp(args[1], "level")) {
3592 curproxy->email_alert.level = get_log_level(args[2]);
3593 if (curproxy->email_alert.level < 0) {
3594 Alert("parsing [%s:%d] : unknown log level '%s' after '%s'\n",
3595 file, linenum, args[1], args[2]);
3596 err_code |= ERR_ALERT | ERR_FATAL;
3597 goto out;
3598 }
3599 }
Simon Horman9dc49962015-01-30 11:22:59 +09003600 else if (!strcmp(args[1], "to")) {
3601 if (*(args[1]) == 0) {
3602 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3603 file, linenum, args[1]);
3604 err_code |= ERR_ALERT | ERR_FATAL;
3605 goto out;
3606 }
3607 free(curproxy->email_alert.to);
3608 curproxy->email_alert.to = strdup(args[2]);
3609 }
3610 else {
3611 Alert("parsing [%s:%d] : email-alert: unknown argument '%s'.\n",
3612 file, linenum, args[1]);
3613 err_code |= ERR_ALERT | ERR_FATAL;
3614 goto out;
3615 }
Simon Horman64e34162015-02-06 11:11:57 +09003616 /* Indicate that the email_alert is at least partially configured */
3617 curproxy->email_alert.set = 1;
Simon Horman9dc49962015-01-30 11:22:59 +09003618 }/* end else if (!strcmp(args[0], "email-alert")) */
Simon Horman98637e52014-06-20 12:30:16 +09003619 else if (!strcmp(args[0], "external-check")) {
3620 if (*(args[1]) == 0) {
3621 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3622 file, linenum, args[0]);
3623 err_code |= ERR_ALERT | ERR_FATAL;
3624 goto out;
3625 }
3626
3627 if (!strcmp(args[1], "command")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003628 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003629 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003630 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003631 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3632 file, linenum, args[1]);
3633 err_code |= ERR_ALERT | ERR_FATAL;
3634 goto out;
3635 }
3636 free(curproxy->check_command);
3637 curproxy->check_command = strdup(args[2]);
3638 }
3639 else if (!strcmp(args[1], "path")) {
Ben Cabot49795eb2015-09-16 12:07:51 +01003640 if (alertif_too_many_args(2, file, linenum, args, &err_code))
William Lallemanddf1425a2015-04-28 20:17:49 +02003641 goto out;
Ben Cabot49795eb2015-09-16 12:07:51 +01003642 if (*(args[2]) == 0) {
Simon Horman98637e52014-06-20 12:30:16 +09003643 Alert("parsing [%s:%d] : missing argument after '%s'.\n",
3644 file, linenum, args[1]);
3645 err_code |= ERR_ALERT | ERR_FATAL;
3646 goto out;
3647 }
3648 free(curproxy->check_path);
3649 curproxy->check_path = strdup(args[2]);
3650 }
3651 else {
3652 Alert("parsing [%s:%d] : external-check: unknown argument '%s'.\n",
3653 file, linenum, args[1]);
3654 err_code |= ERR_ALERT | ERR_FATAL;
3655 goto out;
3656 }
3657 }/* end else if (!strcmp(args[0], "external-check")) */
Emeric Brun647caf12009-06-30 17:57:00 +02003658 else if (!strcmp(args[0], "persist")) { /* persist */
3659 if (*(args[1]) == 0) {
3660 Alert("parsing [%s:%d] : missing persist method.\n",
3661 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003662 err_code |= ERR_ALERT | ERR_FATAL;
3663 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003664 }
3665
3666 if (!strncmp(args[1], "rdp-cookie", 10)) {
3667 curproxy->options2 |= PR_O2_RDPC_PRST;
3668
Emeric Brunb982a3d2010-01-04 15:45:53 +01003669 if (*(args[1] + 10) == '(') { /* cookie name */
Emeric Brun647caf12009-06-30 17:57:00 +02003670 const char *beg, *end;
3671
3672 beg = args[1] + 11;
3673 end = strchr(beg, ')');
3674
William Lallemanddf1425a2015-04-28 20:17:49 +02003675 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3676 goto out;
3677
Emeric Brun647caf12009-06-30 17:57:00 +02003678 if (!end || end == beg) {
3679 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3680 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003681 err_code |= ERR_ALERT | ERR_FATAL;
3682 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003683 }
3684
3685 free(curproxy->rdp_cookie_name);
3686 curproxy->rdp_cookie_name = my_strndup(beg, end - beg);
3687 curproxy->rdp_cookie_len = end-beg;
3688 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01003689 else if (*(args[1] + 10) == '\0') { /* default cookie name 'msts' */
Emeric Brun647caf12009-06-30 17:57:00 +02003690 free(curproxy->rdp_cookie_name);
3691 curproxy->rdp_cookie_name = strdup("msts");
3692 curproxy->rdp_cookie_len = strlen(curproxy->rdp_cookie_name);
3693 }
3694 else { /* syntax */
3695 Alert("parsing [%s:%d] : persist rdp-cookie(name)' requires an rdp cookie name.\n",
3696 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003697 err_code |= ERR_ALERT | ERR_FATAL;
3698 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003699 }
3700 }
3701 else {
3702 Alert("parsing [%s:%d] : unknown persist method.\n",
3703 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02003704 err_code |= ERR_ALERT | ERR_FATAL;
3705 goto out;
Emeric Brun647caf12009-06-30 17:57:00 +02003706 }
3707 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003708 else if (!strcmp(args[0], "appsession")) { /* cookie name */
Willy Tarreau6db62c52015-08-10 19:04:29 +02003709 Alert("parsing [%s:%d] : '%s' is not supported anymore, please check the documentation.\n", file, linenum, args[0]);
3710 err_code |= ERR_ALERT | ERR_FATAL;
3711 goto out;
3712 }
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02003713 else if (!strcmp(args[0], "load-server-state-from-file")) {
3714 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3715 err_code |= ERR_WARN;
3716 if (!strcmp(args[1], "global")) { /* use the file pointed to by global server-state-file directive */
3717 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_GLOBAL;
3718 }
3719 else if (!strcmp(args[1], "local")) { /* use the server-state-file-name variable to locate the server-state file */
3720 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_LOCAL;
3721 }
3722 else if (!strcmp(args[1], "none")) { /* don't use server-state-file directive for this backend */
3723 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
3724 }
3725 else {
3726 Alert("parsing [%s:%d] : '%s' expects 'global', 'local' or 'none'. Got '%s'\n",
3727 file, linenum, args[0], args[1]);
3728 err_code |= ERR_ALERT | ERR_FATAL;
3729 goto out;
3730 }
3731 }
3732 else if (!strcmp(args[0], "server-state-file-name")) {
3733 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3734 err_code |= ERR_WARN;
3735 if (*(args[1]) == 0) {
3736 Alert("parsing [%s:%d] : '%s' expects 'use-backend-name' or a string. Got no argument\n",
3737 file, linenum, args[0]);
3738 err_code |= ERR_ALERT | ERR_FATAL;
3739 goto out;
3740 }
3741 else if (!strcmp(args[1], "use-backend-name"))
3742 curproxy->server_state_file_name = strdup(curproxy->id);
3743 else
3744 curproxy->server_state_file_name = strdup(args[1]);
3745 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003746 else if (!strcmp(args[0], "capture")) {
Willy Tarreau3b6b1a92009-07-23 13:24:23 +02003747 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003748 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003749
Willy Tarreaubaaee002006-06-26 02:48:02 +02003750 if (!strcmp(args[1], "cookie")) { /* name of a cookie to capture */
Cyril Bonté99ed3272010-01-24 23:29:44 +01003751 if (curproxy == &defproxy) {
3752 Alert("parsing [%s:%d] : '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
3753 err_code |= ERR_ALERT | ERR_FATAL;
3754 goto out;
3755 }
3756
William Lallemand1a748ae2015-05-19 16:37:23 +02003757 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3758 goto out;
3759
Willy Tarreaubaaee002006-06-26 02:48:02 +02003760 if (*(args[4]) == 0) {
3761 Alert("parsing [%s:%d] : '%s' expects 'cookie' <cookie_name> 'len' <len>.\n",
3762 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003763 err_code |= ERR_ALERT | ERR_FATAL;
3764 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003765 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02003766 free(curproxy->capture_name);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003767 curproxy->capture_name = strdup(args[2]);
3768 curproxy->capture_namelen = strlen(curproxy->capture_name);
3769 curproxy->capture_len = atol(args[4]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003770 curproxy->to_log |= LW_COOKIE;
3771 }
3772 else if (!strcmp(args[1], "request") && !strcmp(args[2], "header")) {
3773 struct cap_hdr *hdr;
3774
3775 if (curproxy == &defproxy) {
3776 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 +02003777 err_code |= ERR_ALERT | ERR_FATAL;
3778 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003779 }
3780
William Lallemand1a748ae2015-05-19 16:37:23 +02003781 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3782 goto out;
3783
Willy Tarreaubaaee002006-06-26 02:48:02 +02003784 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3785 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3786 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003787 err_code |= ERR_ALERT | ERR_FATAL;
3788 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003789 }
3790
Vincent Bernat02779b62016-04-03 13:48:43 +02003791 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003792 hdr->next = curproxy->req_cap;
3793 hdr->name = strdup(args[3]);
3794 hdr->namelen = strlen(args[3]);
3795 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003796 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003797 hdr->index = curproxy->nb_req_cap++;
3798 curproxy->req_cap = hdr;
3799 curproxy->to_log |= LW_REQHDR;
3800 }
3801 else if (!strcmp(args[1], "response") && !strcmp(args[2], "header")) {
3802 struct cap_hdr *hdr;
3803
3804 if (curproxy == &defproxy) {
3805 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 +02003806 err_code |= ERR_ALERT | ERR_FATAL;
3807 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003808 }
3809
William Lallemand1a748ae2015-05-19 16:37:23 +02003810 if (alertif_too_many_args_idx(4, 1, file, linenum, args, &err_code))
3811 goto out;
3812
Willy Tarreaubaaee002006-06-26 02:48:02 +02003813 if (*(args[3]) == 0 || strcmp(args[4], "len") != 0 || *(args[5]) == 0) {
3814 Alert("parsing [%s:%d] : '%s %s' expects 'header' <header_name> 'len' <len>.\n",
3815 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02003816 err_code |= ERR_ALERT | ERR_FATAL;
3817 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003818 }
Vincent Bernat02779b62016-04-03 13:48:43 +02003819 hdr = calloc(1, sizeof(*hdr));
Willy Tarreaubaaee002006-06-26 02:48:02 +02003820 hdr->next = curproxy->rsp_cap;
3821 hdr->name = strdup(args[3]);
3822 hdr->namelen = strlen(args[3]);
3823 hdr->len = atol(args[5]);
Willy Tarreaucf7f3202007-05-13 22:46:04 +02003824 hdr->pool = create_pool("caphdr", hdr->len + 1, MEM_F_SHARED);
Willy Tarreaubaaee002006-06-26 02:48:02 +02003825 hdr->index = curproxy->nb_rsp_cap++;
3826 curproxy->rsp_cap = hdr;
3827 curproxy->to_log |= LW_RSPHDR;
3828 }
3829 else {
3830 Alert("parsing [%s:%d] : '%s' expects 'cookie' or 'request header' or 'response header'.\n",
3831 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003832 err_code |= ERR_ALERT | ERR_FATAL;
3833 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003834 }
3835 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02003836 else if (!strcmp(args[0], "retries")) { /* connection retries */
Willy Tarreau977b8e42006-12-29 14:19:17 +01003837 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003838 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01003839
William Lallemanddf1425a2015-04-28 20:17:49 +02003840 if (alertif_too_many_args(1, file, linenum, args, &err_code))
3841 goto out;
3842
Willy Tarreaubaaee002006-06-26 02:48:02 +02003843 if (*(args[1]) == 0) {
3844 Alert("parsing [%s:%d] : '%s' expects an integer argument (dispatch counts for one).\n",
3845 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003846 err_code |= ERR_ALERT | ERR_FATAL;
3847 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02003848 }
3849 curproxy->conn_retries = atol(args[1]);
3850 }
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003851 else if (!strcmp(args[0], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003852 struct act_rule *rule;
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003853
3854 if (curproxy == &defproxy) {
3855 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3856 err_code |= ERR_ALERT | ERR_FATAL;
3857 goto out;
3858 }
3859
Willy Tarreau20b0de52012-12-24 15:45:22 +01003860 if (!LIST_ISEMPTY(&curproxy->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003861 !LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003862 (LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3863 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_ACTION_DENY ||
3864 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REDIR ||
3865 LIST_PREV(&curproxy->http_req_rules, struct act_rule *, list)->action == ACT_HTTP_REQ_AUTH)) {
Willy Tarreau20b0de52012-12-24 15:45:22 +01003866 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 +01003867 file, linenum, args[0]);
3868 err_code |= ERR_WARN;
3869 }
3870
Willy Tarreauff011f22011-01-06 17:51:27 +01003871 rule = parse_http_req_cond((const char **)args + 1, file, linenum, curproxy);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003872
Willy Tarreauff011f22011-01-06 17:51:27 +01003873 if (!rule) {
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003874 err_code |= ERR_ALERT | ERR_ABORT;
3875 goto out;
3876 }
3877
Willy Tarreau5002f572014-04-23 01:32:02 +02003878 err_code |= warnif_misplaced_http_req(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003879 err_code |= warnif_cond_conflicts(rule->cond,
3880 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3881 file, linenum);
3882
Willy Tarreauff011f22011-01-06 17:51:27 +01003883 LIST_ADDQ(&curproxy->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki59bb2182010-01-29 17:58:21 +01003884 }
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003885 else if (!strcmp(args[0], "http-response")) { /* response access control */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003886 struct act_rule *rule;
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003887
3888 if (curproxy == &defproxy) {
3889 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3890 err_code |= ERR_ALERT | ERR_FATAL;
3891 goto out;
3892 }
3893
3894 if (!LIST_ISEMPTY(&curproxy->http_res_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003895 !LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->cond &&
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02003896 (LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_ALLOW ||
3897 LIST_PREV(&curproxy->http_res_rules, struct act_rule *, list)->action == ACT_ACTION_DENY)) {
Willy Tarreaue365c0b2013-06-11 16:06:12 +02003898 Warning("parsing [%s:%d]: previous '%s' action is final and has no condition attached, further entries are NOOP.\n",
3899 file, linenum, args[0]);
3900 err_code |= ERR_WARN;
3901 }
3902
3903 rule = parse_http_res_cond((const char **)args + 1, file, linenum, curproxy);
3904
3905 if (!rule) {
3906 err_code |= ERR_ALERT | ERR_ABORT;
3907 goto out;
3908 }
3909
3910 err_code |= warnif_cond_conflicts(rule->cond,
3911 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
3912 file, linenum);
3913
3914 LIST_ADDQ(&curproxy->http_res_rules, &rule->list);
3915 }
Mark Lamourinec2247f02012-01-04 13:02:01 -05003916 else if (!strcmp(args[0], "http-send-name-header")) { /* send server name in request header */
3917 /* set the header name and length into the proxy structure */
3918 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
3919 err_code |= ERR_WARN;
3920
3921 if (!*args[1]) {
3922 Alert("parsing [%s:%d] : '%s' requires a header string.\n",
3923 file, linenum, args[0]);
3924 err_code |= ERR_ALERT | ERR_FATAL;
3925 goto out;
3926 }
3927
3928 /* set the desired header name */
3929 free(curproxy->server_id_hdr_name);
3930 curproxy->server_id_hdr_name = strdup(args[1]);
3931 curproxy->server_id_hdr_len = strlen(curproxy->server_id_hdr_name);
3932 }
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003933 else if (!strcmp(args[0], "block")) { /* early blocking based on ACLs */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02003934 struct act_rule *rule;
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003935
Willy Tarreaub099aca2008-10-12 17:26:37 +02003936 if (curproxy == &defproxy) {
3937 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003938 err_code |= ERR_ALERT | ERR_FATAL;
3939 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003940 }
3941
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003942 /* emulate "block" using "http-request block". Since these rules are supposed to
3943 * be processed before all http-request rules, we put them into their own list
3944 * and will insert them at the end.
3945 */
3946 rule = parse_http_req_cond((const char **)args, file, linenum, curproxy);
3947 if (!rule) {
3948 err_code |= ERR_ALERT | ERR_ABORT;
Willy Tarreau93893792009-07-23 13:19:11 +02003949 goto out;
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003950 }
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02003951 err_code |= warnif_misplaced_block(curproxy, file, linenum, args[0]);
3952 err_code |= warnif_cond_conflicts(rule->cond,
3953 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3954 file, linenum);
3955 LIST_ADDQ(&curproxy->block_rules, &rule->list);
Willy Tarreaude9d2d72014-04-28 22:28:02 +02003956
3957 if (!already_warned(WARN_BLOCK_DEPRECATED))
3958 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]);
3959
Willy Tarreau5c8e3e02007-05-07 00:58:25 +02003960 }
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003961 else if (!strcmp(args[0], "redirect")) {
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003962 struct redirect_rule *rule;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003963
Cyril Bonté99ed3272010-01-24 23:29:44 +01003964 if (curproxy == &defproxy) {
3965 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
3966 err_code |= ERR_ALERT | ERR_FATAL;
3967 goto out;
3968 }
3969
Willy Tarreaube4653b2015-05-28 15:26:58 +02003970 if ((rule = http_parse_redirect_rule(file, linenum, curproxy, (const char **)args + 1, &errmsg, 0, 0)) == NULL) {
Willy Tarreau4baae242012-12-27 12:00:31 +01003971 Alert("parsing [%s:%d] : error detected in %s '%s' while parsing redirect rule : %s.\n",
3972 file, linenum, proxy_type_str(curproxy), curproxy->id, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02003973 err_code |= ERR_ALERT | ERR_FATAL;
3974 goto out;
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003975 }
3976
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003977 LIST_ADDQ(&curproxy->redirect_rules, &rule->list);
Willy Tarreauee445d92014-04-23 01:39:04 +02003978 err_code |= warnif_misplaced_redirect(curproxy, file, linenum, args[0]);
Willy Tarreaua91d0a52013-03-25 08:12:18 +01003979 err_code |= warnif_cond_conflicts(rule->cond,
3980 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
3981 file, linenum);
Willy Tarreaub463dfb2008-06-07 23:08:56 +02003982 }
Krzysztof Piotr Oledzki7b723ef2009-01-27 21:09:41 +01003983 else if (!strcmp(args[0], "use_backend")) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02003984 struct switching_rule *rule;
3985
Willy Tarreaub099aca2008-10-12 17:26:37 +02003986 if (curproxy == &defproxy) {
3987 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003988 err_code |= ERR_ALERT | ERR_FATAL;
3989 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02003990 }
3991
Willy Tarreau55ea7572007-06-17 19:56:27 +02003992 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02003993 err_code |= ERR_WARN;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003994
3995 if (*(args[1]) == 0) {
3996 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02003997 err_code |= ERR_ALERT | ERR_FATAL;
3998 goto out;
Willy Tarreau55ea7572007-06-17 19:56:27 +02003999 }
4000
Willy Tarreauf51658d2014-04-23 01:21:56 +02004001 if (strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0) {
4002 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4003 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4004 file, linenum, errmsg);
4005 err_code |= ERR_ALERT | ERR_FATAL;
4006 goto out;
4007 }
Willy Tarreau55ea7572007-06-17 19:56:27 +02004008
Willy Tarreauf51658d2014-04-23 01:21:56 +02004009 err_code |= warnif_cond_conflicts(cond, SMP_VAL_FE_SET_BCK, file, linenum);
Willy Tarreau55ea7572007-06-17 19:56:27 +02004010 }
4011
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004012 rule = calloc(1, sizeof(*rule));
Willy Tarreau55ea7572007-06-17 19:56:27 +02004013 rule->cond = cond;
4014 rule->be.name = strdup(args[1]);
4015 LIST_INIT(&rule->list);
4016 LIST_ADDQ(&curproxy->switching_rules, &rule->list);
4017 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004018 else if (strcmp(args[0], "use-server") == 0) {
4019 struct server_rule *rule;
4020
4021 if (curproxy == &defproxy) {
4022 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4023 err_code |= ERR_ALERT | ERR_FATAL;
4024 goto out;
4025 }
4026
4027 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
4028 err_code |= ERR_WARN;
4029
4030 if (*(args[1]) == 0) {
4031 Alert("parsing [%s:%d] : '%s' expects a server name.\n", file, linenum, args[0]);
4032 err_code |= ERR_ALERT | ERR_FATAL;
4033 goto out;
4034 }
4035
4036 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4037 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4038 file, linenum, args[0]);
4039 err_code |= ERR_ALERT | ERR_FATAL;
4040 goto out;
4041 }
4042
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004043 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4044 Alert("parsing [%s:%d] : error detected while parsing switching rule : %s.\n",
4045 file, linenum, errmsg);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004046 err_code |= ERR_ALERT | ERR_FATAL;
4047 goto out;
4048 }
4049
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004050 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004051
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004052 rule = calloc(1, sizeof(*rule));
Willy Tarreau4a5cade2012-04-05 21:09:48 +02004053 rule->cond = cond;
4054 rule->srv.name = strdup(args[1]);
4055 LIST_INIT(&rule->list);
4056 LIST_ADDQ(&curproxy->server_rules, &rule->list);
4057 curproxy->be_req_ana |= AN_REQ_SRV_RULES;
4058 }
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004059 else if ((!strcmp(args[0], "force-persist")) ||
4060 (!strcmp(args[0], "ignore-persist"))) {
4061 struct persist_rule *rule;
Willy Tarreau4de91492010-01-22 19:10:05 +01004062
4063 if (curproxy == &defproxy) {
4064 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4065 err_code |= ERR_ALERT | ERR_FATAL;
4066 goto out;
4067 }
4068
4069 if (warnifnotcap(curproxy, PR_CAP_FE|PR_CAP_BE, file, linenum, args[0], NULL))
4070 err_code |= ERR_WARN;
4071
Willy Tarreauef6494c2010-01-28 17:12:36 +01004072 if (strcmp(args[1], "if") != 0 && strcmp(args[1], "unless") != 0) {
Willy Tarreau4de91492010-01-22 19:10:05 +01004073 Alert("parsing [%s:%d] : '%s' requires either 'if' or 'unless' followed by a condition.\n",
4074 file, linenum, args[0]);
4075 err_code |= ERR_ALERT | ERR_FATAL;
4076 goto out;
4077 }
4078
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004079 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 1, &errmsg)) == NULL) {
4080 Alert("parsing [%s:%d] : error detected while parsing a '%s' rule : %s.\n",
4081 file, linenum, args[0], errmsg);
Willy Tarreau4de91492010-01-22 19:10:05 +01004082 err_code |= ERR_ALERT | ERR_FATAL;
4083 goto out;
4084 }
4085
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004086 /* note: BE_REQ_CNT is the first one after FE_SET_BCK, which is
4087 * where force-persist is applied.
4088 */
4089 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_REQ_CNT, file, linenum);
Willy Tarreau4de91492010-01-22 19:10:05 +01004090
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004091 rule = calloc(1, sizeof(*rule));
Willy Tarreau4de91492010-01-22 19:10:05 +01004092 rule->cond = cond;
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004093 if (!strcmp(args[0], "force-persist")) {
4094 rule->type = PERSIST_TYPE_FORCE;
4095 } else {
4096 rule->type = PERSIST_TYPE_IGNORE;
4097 }
Willy Tarreau4de91492010-01-22 19:10:05 +01004098 LIST_INIT(&rule->list);
Cyril Bonté47fdd8e2010-04-25 00:00:51 +02004099 LIST_ADDQ(&curproxy->persist_rules, &rule->list);
Willy Tarreau4de91492010-01-22 19:10:05 +01004100 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004101 else if (!strcmp(args[0], "stick-table")) {
4102 int myidx = 1;
Willy Tarreaue45288c2015-05-26 10:49:46 +02004103 struct proxy *other;
4104
Willy Tarreaue2dc1fa2015-05-26 12:08:07 +02004105 other = proxy_tbl_by_name(curproxy->id);
Willy Tarreaue45288c2015-05-26 10:49:46 +02004106 if (other) {
4107 Alert("parsing [%s:%d] : stick-table name '%s' conflicts with table declared in %s '%s' at %s:%d.\n",
4108 file, linenum, curproxy->id, proxy_type_str(other), other->id, other->conf.file, other->conf.line);
4109 err_code |= ERR_ALERT | ERR_FATAL;
4110 goto out;
4111 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004112
Emeric Brun32da3c42010-09-23 18:39:19 +02004113 curproxy->table.id = curproxy->id;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004114 curproxy->table.type = (unsigned int)-1;
4115 while (*args[myidx]) {
4116 const char *err;
4117
4118 if (strcmp(args[myidx], "size") == 0) {
4119 myidx++;
4120 if (!*(args[myidx])) {
4121 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4122 file, linenum, args[myidx-1]);
4123 err_code |= ERR_ALERT | ERR_FATAL;
4124 goto out;
4125 }
4126 if ((err = parse_size_err(args[myidx], &curproxy->table.size))) {
4127 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4128 file, linenum, *err, args[myidx-1]);
4129 err_code |= ERR_ALERT | ERR_FATAL;
4130 goto out;
4131 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004132 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004133 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004134 else if (strcmp(args[myidx], "peers") == 0) {
4135 myidx++;
Godbach50523162013-12-11 19:48:57 +08004136 if (!*(args[myidx])) {
Godbachff115542014-04-21 21:52:23 +08004137 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4138 file, linenum, args[myidx-1]);
4139 err_code |= ERR_ALERT | ERR_FATAL;
4140 goto out;
Godbach50523162013-12-11 19:48:57 +08004141 }
Emeric Brun32da3c42010-09-23 18:39:19 +02004142 curproxy->table.peers.name = strdup(args[myidx++]);
4143 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004144 else if (strcmp(args[myidx], "expire") == 0) {
4145 myidx++;
4146 if (!*(args[myidx])) {
4147 Alert("parsing [%s:%d] : stick-table: missing argument after '%s'.\n",
4148 file, linenum, args[myidx-1]);
4149 err_code |= ERR_ALERT | ERR_FATAL;
4150 goto out;
4151 }
4152 err = parse_time_err(args[myidx], &val, TIME_UNIT_MS);
4153 if (err) {
4154 Alert("parsing [%s:%d] : stick-table: unexpected character '%c' in argument of '%s'.\n",
4155 file, linenum, *err, args[myidx-1]);
4156 err_code |= ERR_ALERT | ERR_FATAL;
4157 goto out;
4158 }
Ben Cabot3b90f0a2016-01-20 09:44:39 +00004159 if (val > INT_MAX) {
4160 Alert("parsing [%s:%d] : Expire value [%u]ms exceeds maxmimum value of 24.85 days.\n",
4161 file, linenum, val);
4162 err_code |= ERR_ALERT | ERR_FATAL;
4163 goto out;
4164 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004165 curproxy->table.expire = val;
Willy Tarreau0c559312010-01-26 18:36:26 +01004166 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004167 }
4168 else if (strcmp(args[myidx], "nopurge") == 0) {
4169 curproxy->table.nopurge = 1;
Willy Tarreau0c559312010-01-26 18:36:26 +01004170 myidx++;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004171 }
4172 else if (strcmp(args[myidx], "type") == 0) {
4173 myidx++;
4174 if (stktable_parse_type(args, &myidx, &curproxy->table.type, &curproxy->table.key_size) != 0) {
4175 Alert("parsing [%s:%d] : stick-table: unknown type '%s'.\n",
4176 file, linenum, args[myidx]);
4177 err_code |= ERR_ALERT | ERR_FATAL;
4178 goto out;
4179 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004180 /* myidx already points to next arg */
4181 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004182 else if (strcmp(args[myidx], "store") == 0) {
Willy Tarreauac782882010-06-20 10:41:54 +02004183 int type, err;
Willy Tarreau888617d2010-06-20 09:11:39 +02004184 char *cw, *nw, *sa;
Willy Tarreau08d5f982010-06-06 13:34:54 +02004185
4186 myidx++;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004187 nw = args[myidx];
4188 while (*nw) {
4189 /* the "store" keyword supports a comma-separated list */
4190 cw = nw;
Willy Tarreau888617d2010-06-20 09:11:39 +02004191 sa = NULL; /* store arg */
4192 while (*nw && *nw != ',') {
4193 if (*nw == '(') {
4194 *nw = 0;
4195 sa = ++nw;
4196 while (*nw != ')') {
4197 if (!*nw) {
4198 Alert("parsing [%s:%d] : %s: missing closing parenthesis after store option '%s'.\n",
4199 file, linenum, args[0], cw);
4200 err_code |= ERR_ALERT | ERR_FATAL;
4201 goto out;
4202 }
4203 nw++;
4204 }
4205 *nw = '\0';
4206 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004207 nw++;
Willy Tarreau888617d2010-06-20 09:11:39 +02004208 }
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004209 if (*nw)
4210 *nw++ = '\0';
4211 type = stktable_get_data_type(cw);
4212 if (type < 0) {
4213 Alert("parsing [%s:%d] : %s: unknown store option '%s'.\n",
4214 file, linenum, args[0], cw);
4215 err_code |= ERR_ALERT | ERR_FATAL;
4216 goto out;
4217 }
Willy Tarreauac782882010-06-20 10:41:54 +02004218
4219 err = stktable_alloc_data_type(&curproxy->table, type, sa);
4220 switch (err) {
4221 case PE_NONE: break;
4222 case PE_EXIST:
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004223 Warning("parsing [%s:%d]: %s: store option '%s' already enabled, ignored.\n",
4224 file, linenum, args[0], cw);
4225 err_code |= ERR_WARN;
Willy Tarreauac782882010-06-20 10:41:54 +02004226 break;
4227
4228 case PE_ARG_MISSING:
4229 Alert("parsing [%s:%d] : %s: missing argument to store option '%s'.\n",
4230 file, linenum, args[0], cw);
4231 err_code |= ERR_ALERT | ERR_FATAL;
4232 goto out;
4233
4234 case PE_ARG_NOT_USED:
4235 Alert("parsing [%s:%d] : %s: unexpected argument to store option '%s'.\n",
4236 file, linenum, args[0], cw);
4237 err_code |= ERR_ALERT | ERR_FATAL;
4238 goto out;
4239
4240 default:
4241 Alert("parsing [%s:%d] : %s: error when processing store option '%s'.\n",
4242 file, linenum, args[0], cw);
4243 err_code |= ERR_ALERT | ERR_FATAL;
4244 goto out;
Willy Tarreaub084e9c2010-06-19 07:12:36 +02004245 }
Willy Tarreau08d5f982010-06-06 13:34:54 +02004246 }
4247 myidx++;
4248 }
Willy Tarreau0c559312010-01-26 18:36:26 +01004249 else {
4250 Alert("parsing [%s:%d] : stick-table: unknown argument '%s'.\n",
4251 file, linenum, args[myidx]);
4252 err_code |= ERR_ALERT | ERR_FATAL;
4253 goto out;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004254 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004255 }
4256
4257 if (!curproxy->table.size) {
4258 Alert("parsing [%s:%d] : stick-table: missing size.\n",
4259 file, linenum);
4260 err_code |= ERR_ALERT | ERR_FATAL;
4261 goto out;
4262 }
4263
4264 if (curproxy->table.type == (unsigned int)-1) {
4265 Alert("parsing [%s:%d] : stick-table: missing type.\n",
4266 file, linenum);
4267 err_code |= ERR_ALERT | ERR_FATAL;
4268 goto out;
4269 }
4270 }
4271 else if (!strcmp(args[0], "stick")) {
Emeric Brunb982a3d2010-01-04 15:45:53 +01004272 struct sticking_rule *rule;
Willy Tarreau12785782012-04-27 21:37:17 +02004273 struct sample_expr *expr;
Emeric Brunb982a3d2010-01-04 15:45:53 +01004274 int myidx = 0;
4275 const char *name = NULL;
4276 int flags;
4277
4278 if (curproxy == &defproxy) {
4279 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4280 err_code |= ERR_ALERT | ERR_FATAL;
4281 goto out;
4282 }
4283
4284 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL)) {
4285 err_code |= ERR_WARN;
4286 goto out;
4287 }
4288
4289 myidx++;
4290 if ((strcmp(args[myidx], "store") == 0) ||
4291 (strcmp(args[myidx], "store-request") == 0)) {
4292 myidx++;
4293 flags = STK_IS_STORE;
4294 }
4295 else if (strcmp(args[myidx], "store-response") == 0) {
4296 myidx++;
4297 flags = STK_IS_STORE | STK_ON_RSP;
4298 }
4299 else if (strcmp(args[myidx], "match") == 0) {
4300 myidx++;
4301 flags = STK_IS_MATCH;
4302 }
4303 else if (strcmp(args[myidx], "on") == 0) {
4304 myidx++;
4305 flags = STK_IS_MATCH | STK_IS_STORE;
4306 }
4307 else {
4308 Alert("parsing [%s:%d] : '%s' expects 'on', 'match', or 'store'.\n", file, linenum, args[0]);
4309 err_code |= ERR_ALERT | ERR_FATAL;
4310 goto out;
4311 }
4312
4313 if (*(args[myidx]) == 0) {
4314 Alert("parsing [%s:%d] : '%s' expects a fetch method.\n", file, linenum, args[0]);
4315 err_code |= ERR_ALERT | ERR_FATAL;
4316 goto out;
4317 }
4318
Willy Tarreaua4312fa2013-04-02 16:34:32 +02004319 curproxy->conf.args.ctx = ARGC_STK;
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01004320 expr = sample_parse_expr(args, &myidx, file, linenum, &errmsg, &curproxy->conf.args);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004321 if (!expr) {
Willy Tarreau975c1782013-12-12 23:16:54 +01004322 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004323 err_code |= ERR_ALERT | ERR_FATAL;
4324 goto out;
4325 }
4326
4327 if (flags & STK_ON_RSP) {
Willy Tarreau80aca902013-01-07 15:42:20 +01004328 if (!(expr->fetch->val & SMP_VAL_BE_STO_RUL)) {
4329 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available for 'store-response'.\n",
4330 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004331 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004332 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004333 goto out;
4334 }
4335 } else {
Willy Tarreau80aca902013-01-07 15:42:20 +01004336 if (!(expr->fetch->val & SMP_VAL_BE_SET_SRV)) {
4337 Alert("parsing [%s:%d] : '%s': fetch method '%s' extracts information from '%s', none of which is available during request.\n",
4338 file, linenum, args[0], expr->fetch->kw, sample_src_names(expr->fetch->use));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004339 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004340 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004341 goto out;
4342 }
4343 }
4344
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004345 /* check if we need to allocate an hdr_idx struct for HTTP parsing */
Willy Tarreau25320b22013-03-24 07:22:08 +01004346 curproxy->http_needed |= !!(expr->fetch->use & SMP_USE_HTTP_ANY);
Willy Tarreau1b6c00c2012-10-05 22:41:26 +02004347
Emeric Brunb982a3d2010-01-04 15:45:53 +01004348 if (strcmp(args[myidx], "table") == 0) {
4349 myidx++;
4350 name = args[myidx++];
4351 }
4352
Willy Tarreauef6494c2010-01-28 17:12:36 +01004353 if (strcmp(args[myidx], "if") == 0 || strcmp(args[myidx], "unless") == 0) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004354 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + myidx, &errmsg)) == NULL) {
4355 Alert("parsing [%s:%d] : '%s': error detected while parsing sticking condition : %s.\n",
4356 file, linenum, args[0], errmsg);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004357 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004358 free(expr);
Emeric Brunb982a3d2010-01-04 15:45:53 +01004359 goto out;
4360 }
Emeric Brunb982a3d2010-01-04 15:45:53 +01004361 }
Willy Tarreauef6494c2010-01-28 17:12:36 +01004362 else if (*(args[myidx])) {
4363 Alert("parsing [%s:%d] : '%s': unknown keyword '%s'.\n",
4364 file, linenum, args[0], args[myidx]);
4365 err_code |= ERR_ALERT | ERR_FATAL;
Simon Horman5e55f5d2011-07-15 13:14:07 +09004366 free(expr);
Willy Tarreauef6494c2010-01-28 17:12:36 +01004367 goto out;
4368 }
Emeric Brun97679e72010-09-23 17:56:44 +02004369 if (flags & STK_ON_RSP)
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004370 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_STO_RUL, file, linenum);
Emeric Brun97679e72010-09-23 17:56:44 +02004371 else
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004372 err_code |= warnif_cond_conflicts(cond, SMP_VAL_BE_SET_SRV, file, linenum);
Willy Tarreauf1e98b82010-01-28 17:59:39 +01004373
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004374 rule = calloc(1, sizeof(*rule));
Emeric Brunb982a3d2010-01-04 15:45:53 +01004375 rule->cond = cond;
4376 rule->expr = expr;
4377 rule->flags = flags;
4378 rule->table.name = name ? strdup(name) : NULL;
4379 LIST_INIT(&rule->list);
4380 if (flags & STK_ON_RSP)
4381 LIST_ADDQ(&curproxy->storersp_rules, &rule->list);
4382 else
4383 LIST_ADDQ(&curproxy->sticking_rules, &rule->list);
4384 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004385 else if (!strcmp(args[0], "stats")) {
4386 if (curproxy != &defproxy && curproxy->uri_auth == defproxy.uri_auth)
4387 curproxy->uri_auth = NULL; /* we must detach from the default config */
4388
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004389 if (!*args[1]) {
4390 goto stats_error_parsing;
Cyril Bonté474be412010-10-12 00:14:36 +02004391 } else if (!strcmp(args[1], "admin")) {
4392 struct stats_admin_rule *rule;
4393
4394 if (curproxy == &defproxy) {
4395 Alert("parsing [%s:%d]: '%s %s' not allowed in 'defaults' section.\n", file, linenum, args[0], args[1]);
4396 err_code |= ERR_ALERT | ERR_FATAL;
4397 goto out;
4398 }
4399
4400 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4401 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4402 err_code |= ERR_ALERT | ERR_ABORT;
4403 goto out;
4404 }
4405
4406 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
4407 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
4408 file, linenum, args[0], args[1]);
4409 err_code |= ERR_ALERT | ERR_FATAL;
4410 goto out;
4411 }
Willy Tarreaub7451bb2012-04-27 12:38:15 +02004412 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
4413 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' rule : %s.\n",
4414 file, linenum, args[0], args[1], errmsg);
Cyril Bonté474be412010-10-12 00:14:36 +02004415 err_code |= ERR_ALERT | ERR_FATAL;
4416 goto out;
4417 }
4418
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004419 err_code |= warnif_cond_conflicts(cond,
4420 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4421 file, linenum);
Cyril Bonté474be412010-10-12 00:14:36 +02004422
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004423 rule = calloc(1, sizeof(*rule));
Cyril Bonté474be412010-10-12 00:14:36 +02004424 rule->cond = cond;
4425 LIST_INIT(&rule->list);
4426 LIST_ADDQ(&curproxy->uri_auth->admin_rules, &rule->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004427 } else if (!strcmp(args[1], "uri")) {
4428 if (*(args[2]) == 0) {
4429 Alert("parsing [%s:%d] : 'uri' needs an URI prefix.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004430 err_code |= ERR_ALERT | ERR_FATAL;
4431 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004432 } else if (!stats_set_uri(&curproxy->uri_auth, args[2])) {
4433 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004434 err_code |= ERR_ALERT | ERR_ABORT;
4435 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004436 }
4437 } else if (!strcmp(args[1], "realm")) {
4438 if (*(args[2]) == 0) {
4439 Alert("parsing [%s:%d] : 'realm' needs an realm name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004440 err_code |= ERR_ALERT | ERR_FATAL;
4441 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004442 } else if (!stats_set_realm(&curproxy->uri_auth, args[2])) {
4443 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004444 err_code |= ERR_ALERT | ERR_ABORT;
4445 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004446 }
Willy Tarreaubbd42122007-07-25 07:26:38 +02004447 } else if (!strcmp(args[1], "refresh")) {
Willy Tarreaub3f32f52007-12-02 22:15:14 +01004448 unsigned interval;
4449
4450 err = parse_time_err(args[2], &interval, TIME_UNIT_S);
4451 if (err) {
4452 Alert("parsing [%s:%d] : unexpected character '%c' in stats refresh interval.\n",
4453 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02004454 err_code |= ERR_ALERT | ERR_FATAL;
4455 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004456 } else if (!stats_set_refresh(&curproxy->uri_auth, interval)) {
4457 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004458 err_code |= ERR_ALERT | ERR_ABORT;
4459 goto out;
Willy Tarreaubbd42122007-07-25 07:26:38 +02004460 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004461 } else if (!strcmp(args[1], "http-request")) { /* request access control: allow/deny/auth */
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004462 struct act_rule *rule;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004463
4464 if (curproxy == &defproxy) {
4465 Alert("parsing [%s:%d]: '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
4466 err_code |= ERR_ALERT | ERR_FATAL;
4467 goto out;
4468 }
4469
4470 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4471 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4472 err_code |= ERR_ALERT | ERR_ABORT;
4473 goto out;
4474 }
4475
Willy Tarreauff011f22011-01-06 17:51:27 +01004476 if (!LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02004477 !LIST_PREV(&curproxy->uri_auth->http_req_rules, struct act_rule *, list)->cond) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004478 Warning("parsing [%s:%d]: previous '%s' action has no condition attached, further entries are NOOP.\n",
4479 file, linenum, args[0]);
4480 err_code |= ERR_WARN;
4481 }
4482
Willy Tarreauff011f22011-01-06 17:51:27 +01004483 rule = parse_http_req_cond((const char **)args + 2, file, linenum, curproxy);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004484
Willy Tarreauff011f22011-01-06 17:51:27 +01004485 if (!rule) {
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004486 err_code |= ERR_ALERT | ERR_ABORT;
4487 goto out;
4488 }
4489
Willy Tarreaua91d0a52013-03-25 08:12:18 +01004490 err_code |= warnif_cond_conflicts(rule->cond,
4491 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
4492 file, linenum);
Willy Tarreauff011f22011-01-06 17:51:27 +01004493 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01004494
Willy Tarreaubaaee002006-06-26 02:48:02 +02004495 } else if (!strcmp(args[1], "auth")) {
4496 if (*(args[2]) == 0) {
4497 Alert("parsing [%s:%d] : 'auth' needs a user:password account.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004498 err_code |= ERR_ALERT | ERR_FATAL;
4499 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004500 } else if (!stats_add_auth(&curproxy->uri_auth, args[2])) {
4501 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004502 err_code |= ERR_ALERT | ERR_ABORT;
4503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004504 }
4505 } else if (!strcmp(args[1], "scope")) {
4506 if (*(args[2]) == 0) {
4507 Alert("parsing [%s:%d] : 'scope' needs a proxy name.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004508 err_code |= ERR_ALERT | ERR_FATAL;
4509 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004510 } else if (!stats_add_scope(&curproxy->uri_auth, args[2])) {
4511 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004512 err_code |= ERR_ALERT | ERR_ABORT;
4513 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004514 }
4515 } else if (!strcmp(args[1], "enable")) {
4516 if (!stats_check_init_uri_auth(&curproxy->uri_auth)) {
4517 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004518 err_code |= ERR_ALERT | ERR_ABORT;
4519 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004520 }
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004521 } else if (!strcmp(args[1], "hide-version")) {
4522 if (!stats_set_flag(&curproxy->uri_auth, ST_HIDEVER)) {
4523 Alert("parsing [%s:%d] : out of memory.\n", file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02004524 err_code |= ERR_ALERT | ERR_ABORT;
4525 goto out;
Krzysztof Oledzkid9db9272007-10-15 10:05:11 +02004526 }
Krzysztof Piotr Oledzki15514c22010-01-04 16:03:09 +01004527 } else if (!strcmp(args[1], "show-legends")) {
4528 if (!stats_set_flag(&curproxy->uri_auth, ST_SHLGNDS)) {
4529 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4530 err_code |= ERR_ALERT | ERR_ABORT;
4531 goto out;
4532 }
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004533 } else if (!strcmp(args[1], "show-node")) {
4534
4535 if (*args[2]) {
4536 int i;
4537 char c;
4538
4539 for (i=0; args[2][i]; i++) {
4540 c = args[2][i];
Willy Tarreau88e05812010-03-03 00:16:00 +01004541 if (!isupper((unsigned char)c) && !islower((unsigned char)c) &&
4542 !isdigit((unsigned char)c) && c != '_' && c != '-' && c != '.')
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004543 break;
4544 }
4545
4546 if (!i || args[2][i]) {
4547 Alert("parsing [%s:%d]: '%s %s' invalid node name - should be a string"
4548 "with digits(0-9), letters(A-Z, a-z), hyphen(-) or underscode(_).\n",
4549 file, linenum, args[0], args[1]);
4550 err_code |= ERR_ALERT | ERR_FATAL;
4551 goto out;
4552 }
4553 }
4554
4555 if (!stats_set_node(&curproxy->uri_auth, args[2])) {
4556 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4557 err_code |= ERR_ALERT | ERR_ABORT;
4558 goto out;
4559 }
4560 } else if (!strcmp(args[1], "show-desc")) {
4561 char *desc = NULL;
4562
4563 if (*args[2]) {
4564 int i, len=0;
4565 char *d;
4566
Willy Tarreau348acfe2014-04-14 15:00:39 +02004567 for (i = 2; *args[i]; i++)
4568 len += strlen(args[i]) + 1;
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004569
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004570 desc = d = calloc(1, len);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004571
Willy Tarreau348acfe2014-04-14 15:00:39 +02004572 d += snprintf(d, desc + len - d, "%s", args[2]);
4573 for (i = 3; *args[i]; i++)
4574 d += snprintf(d, desc + len - d, " %s", args[i]);
Krzysztof Piotr Oledzki48cb2ae2009-10-02 22:51:14 +02004575 }
4576
4577 if (!*args[2] && !global.desc)
4578 Warning("parsing [%s:%d]: '%s' requires a parameter or 'desc' to be set in the global section.\n",
4579 file, linenum, args[1]);
4580 else {
4581 if (!stats_set_desc(&curproxy->uri_auth, desc)) {
4582 free(desc);
4583 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
4584 err_code |= ERR_ALERT | ERR_ABORT;
4585 goto out;
4586 }
4587 free(desc);
4588 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004589 } else {
Krzysztof Piotr Oledzki260a3bb2010-01-06 16:25:05 +01004590stats_error_parsing:
Cyril Bonté474be412010-10-12 00:14:36 +02004591 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 +01004592 file, linenum, *args[1]?"unknown stats parameter":"missing keyword in", args[*args[1]?1:0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004593 err_code |= ERR_ALERT | ERR_FATAL;
4594 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004595 }
4596 }
4597 else if (!strcmp(args[0], "option")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004598 int optnum;
4599
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004600 if (*(args[1]) == '\0') {
4601 Alert("parsing [%s:%d]: '%s' expects an option name.\n",
4602 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02004603 err_code |= ERR_ALERT | ERR_FATAL;
4604 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004605 }
Willy Tarreau13943ab2006-12-31 00:24:10 +01004606
4607 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
4608 if (!strcmp(args[1], cfg_opts[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004609 if (cfg_opts[optnum].cap == PR_CAP_NONE) {
4610 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4611 file, linenum, cfg_opts[optnum].name);
4612 err_code |= ERR_ALERT | ERR_FATAL;
4613 goto out;
4614 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004615 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4616 goto out;
4617
Willy Tarreau93893792009-07-23 13:19:11 +02004618 if (warnifnotcap(curproxy, cfg_opts[optnum].cap, file, linenum, args[1], NULL)) {
4619 err_code |= ERR_WARN;
4620 goto out;
4621 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004622
Willy Tarreau3842f002009-06-14 11:39:52 +02004623 curproxy->no_options &= ~cfg_opts[optnum].val;
4624 curproxy->options &= ~cfg_opts[optnum].val;
4625
4626 switch (kwm) {
4627 case KWM_STD:
4628 curproxy->options |= cfg_opts[optnum].val;
4629 break;
4630 case KWM_NO:
4631 curproxy->no_options |= cfg_opts[optnum].val;
4632 break;
4633 case KWM_DEF: /* already cleared */
4634 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004635 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004636
Willy Tarreau93893792009-07-23 13:19:11 +02004637 goto out;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004638 }
4639 }
4640
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004641 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
4642 if (!strcmp(args[1], cfg_opts2[optnum].name)) {
Cyril Bonté62846b22010-11-01 19:26:00 +01004643 if (cfg_opts2[optnum].cap == PR_CAP_NONE) {
4644 Alert("parsing [%s:%d]: option '%s' is not supported due to build options.\n",
4645 file, linenum, cfg_opts2[optnum].name);
4646 err_code |= ERR_ALERT | ERR_FATAL;
4647 goto out;
4648 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004649 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4650 goto out;
Willy Tarreau93893792009-07-23 13:19:11 +02004651 if (warnifnotcap(curproxy, cfg_opts2[optnum].cap, file, linenum, args[1], NULL)) {
4652 err_code |= ERR_WARN;
4653 goto out;
4654 }
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004655
Willy Tarreau3842f002009-06-14 11:39:52 +02004656 curproxy->no_options2 &= ~cfg_opts2[optnum].val;
4657 curproxy->options2 &= ~cfg_opts2[optnum].val;
4658
4659 switch (kwm) {
4660 case KWM_STD:
4661 curproxy->options2 |= cfg_opts2[optnum].val;
4662 break;
4663 case KWM_NO:
4664 curproxy->no_options2 |= cfg_opts2[optnum].val;
4665 break;
4666 case KWM_DEF: /* already cleared */
4667 break;
Willy Tarreau84b57da2009-06-14 11:10:45 +02004668 }
Willy Tarreau93893792009-07-23 13:19:11 +02004669 goto out;
Willy Tarreau66aa61f2009-01-18 21:44:07 +01004670 }
4671 }
4672
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004673 /* HTTP options override each other. They can be cancelled using
4674 * "no option xxx" which only switches to default mode if the mode
4675 * was this one (useful for cancelling options set in defaults
4676 * sections).
4677 */
4678 if (strcmp(args[1], "httpclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004679 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4680 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004681 if (kwm == KWM_STD) {
4682 curproxy->options &= ~PR_O_HTTP_MODE;
4683 curproxy->options |= PR_O_HTTP_PCL;
4684 goto out;
4685 }
4686 else if (kwm == KWM_NO) {
4687 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_PCL)
4688 curproxy->options &= ~PR_O_HTTP_MODE;
4689 goto out;
4690 }
4691 }
4692 else if (strcmp(args[1], "forceclose") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004693 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4694 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004695 if (kwm == KWM_STD) {
4696 curproxy->options &= ~PR_O_HTTP_MODE;
4697 curproxy->options |= PR_O_HTTP_FCL;
4698 goto out;
4699 }
4700 else if (kwm == KWM_NO) {
4701 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_FCL)
4702 curproxy->options &= ~PR_O_HTTP_MODE;
4703 goto out;
4704 }
4705 }
4706 else if (strcmp(args[1], "http-server-close") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004707 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4708 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004709 if (kwm == KWM_STD) {
4710 curproxy->options &= ~PR_O_HTTP_MODE;
4711 curproxy->options |= PR_O_HTTP_SCL;
4712 goto out;
4713 }
4714 else if (kwm == KWM_NO) {
4715 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_SCL)
4716 curproxy->options &= ~PR_O_HTTP_MODE;
4717 goto out;
4718 }
4719 }
4720 else if (strcmp(args[1], "http-keep-alive") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004721 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4722 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004723 if (kwm == KWM_STD) {
4724 curproxy->options &= ~PR_O_HTTP_MODE;
4725 curproxy->options |= PR_O_HTTP_KAL;
4726 goto out;
4727 }
4728 else if (kwm == KWM_NO) {
4729 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_KAL)
4730 curproxy->options &= ~PR_O_HTTP_MODE;
4731 goto out;
4732 }
4733 }
4734 else if (strcmp(args[1], "http-tunnel") == 0) {
William Lallemanddf1425a2015-04-28 20:17:49 +02004735 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4736 goto out;
Willy Tarreau02bce8b2014-01-30 00:15:28 +01004737 if (kwm == KWM_STD) {
4738 curproxy->options &= ~PR_O_HTTP_MODE;
4739 curproxy->options |= PR_O_HTTP_TUN;
4740 goto out;
4741 }
4742 else if (kwm == KWM_NO) {
4743 if ((curproxy->options & PR_O_HTTP_MODE) == PR_O_HTTP_TUN)
4744 curproxy->options &= ~PR_O_HTTP_MODE;
4745 goto out;
4746 }
4747 }
4748
Joseph Lynch726ab712015-05-11 23:25:34 -07004749 /* Redispatch can take an integer argument that control when the
4750 * resispatch occurs. All values are relative to the retries option.
4751 * This can be cancelled using "no option xxx".
4752 */
4753 if (strcmp(args[1], "redispatch") == 0) {
4754 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL)) {
4755 err_code |= ERR_WARN;
4756 goto out;
4757 }
4758
4759 curproxy->no_options &= ~PR_O_REDISP;
4760 curproxy->options &= ~PR_O_REDISP;
4761
4762 switch (kwm) {
4763 case KWM_STD:
4764 curproxy->options |= PR_O_REDISP;
4765 curproxy->redispatch_after = -1;
4766 if(*args[2]) {
4767 curproxy->redispatch_after = atol(args[2]);
4768 }
4769 break;
4770 case KWM_NO:
4771 curproxy->no_options |= PR_O_REDISP;
4772 curproxy->redispatch_after = 0;
4773 break;
4774 case KWM_DEF: /* already cleared */
4775 break;
4776 }
4777 goto out;
4778 }
4779
Willy Tarreau3842f002009-06-14 11:39:52 +02004780 if (kwm != KWM_STD) {
4781 Alert("parsing [%s:%d]: negation/default is not supported for option '%s'.\n",
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004782 file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004783 err_code |= ERR_ALERT | ERR_FATAL;
4784 goto out;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01004785 }
4786
Emeric Brun3a058f32009-06-30 18:26:00 +02004787 if (!strcmp(args[1], "httplog")) {
William Lallemand723b73a2012-02-08 16:37:49 +01004788 char *logformat;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004789 /* generate a complete HTTP log */
William Lallemand723b73a2012-02-08 16:37:49 +01004790 logformat = default_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004791 if (*(args[2]) != '\0') {
4792 if (!strcmp(args[2], "clf")) {
4793 curproxy->options2 |= PR_O2_CLFLOG;
William Lallemand723b73a2012-02-08 16:37:49 +01004794 logformat = clf_http_log_format;
Emeric Brun3a058f32009-06-30 18:26:00 +02004795 } else {
William Lallemand77063bc2015-05-28 18:02:48 +02004796 Alert("parsing [%s:%d] : keyword '%s' only supports option 'clf'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02004797 err_code |= ERR_ALERT | ERR_FATAL;
4798 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004799 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004800 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
4801 goto out;
Emeric Brun3a058f32009-06-30 18:26:00 +02004802 }
Willy Tarreau62a61232013-04-12 18:13:46 +02004803 if (curproxy->conf.logformat_string != default_http_log_format &&
4804 curproxy->conf.logformat_string != default_tcp_log_format &&
4805 curproxy->conf.logformat_string != clf_http_log_format)
4806 free(curproxy->conf.logformat_string);
4807 curproxy->conf.logformat_string = logformat;
4808
4809 free(curproxy->conf.lfs_file);
4810 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4811 curproxy->conf.lfs_line = curproxy->conf.args.line;
Emeric Brun3a058f32009-06-30 18:26:00 +02004812 }
William Lallemandbddd4fd2012-02-27 11:23:10 +01004813 else if (!strcmp(args[1], "tcplog")) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02004814 /* generate a detailed TCP log */
Willy Tarreau62a61232013-04-12 18:13:46 +02004815 if (curproxy->conf.logformat_string != default_http_log_format &&
4816 curproxy->conf.logformat_string != default_tcp_log_format &&
4817 curproxy->conf.logformat_string != clf_http_log_format)
4818 free(curproxy->conf.logformat_string);
4819 curproxy->conf.logformat_string = default_tcp_log_format;
4820
4821 free(curproxy->conf.lfs_file);
4822 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
4823 curproxy->conf.lfs_line = curproxy->conf.args.line;
William Lallemanddf1425a2015-04-28 20:17:49 +02004824
4825 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4826 goto out;
William Lallemandbddd4fd2012-02-27 11:23:10 +01004827 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02004828 else if (!strcmp(args[1], "tcpka")) {
Willy Tarreau87b09662015-04-03 00:22:06 +02004829 /* enable TCP keep-alives on client and server streams */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004830 if (warnifnotcap(curproxy, PR_CAP_BE | PR_CAP_FE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004831 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004832
William Lallemanddf1425a2015-04-28 20:17:49 +02004833 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4834 goto out;
4835
Willy Tarreau13943ab2006-12-31 00:24:10 +01004836 if (curproxy->cap & PR_CAP_FE)
4837 curproxy->options |= PR_O_TCP_CLI_KA;
4838 if (curproxy->cap & PR_CAP_BE)
4839 curproxy->options |= PR_O_TCP_SRV_KA;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004840 }
4841 else if (!strcmp(args[1], "httpchk")) {
Willy Tarreau13943ab2006-12-31 00:24:10 +01004842 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004843 err_code |= ERR_WARN;
4844
Willy Tarreaubaaee002006-06-26 02:48:02 +02004845 /* use HTTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004846 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004847 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004848 curproxy->options2 &= ~PR_O2_CHK_ANY;
4849 curproxy->options2 |= PR_O2_HTTP_CHK;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004850 if (!*args[2]) { /* no argument */
4851 curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
4852 curproxy->check_len = strlen(DEF_CHECK_REQ);
4853 } else if (!*args[3]) { /* one argument : URI */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004854 int reqlen = strlen(args[2]) + strlen("OPTIONS HTTP/1.0\r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004855 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004856 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004857 "OPTIONS %s HTTP/1.0\r\n", args[2]); /* URI to use */
Willy Tarreaubaaee002006-06-26 02:48:02 +02004858 } else { /* more arguments : METHOD URI [HTTP_VER] */
Willy Tarreaue9d87882010-01-27 11:28:42 +01004859 int reqlen = strlen(args[2]) + strlen(args[3]) + 3 + strlen("\r\n");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004860 if (*args[4])
4861 reqlen += strlen(args[4]);
4862 else
4863 reqlen += strlen("HTTP/1.0");
4864
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004865 curproxy->check_req = malloc(reqlen);
Willy Tarreaubaaee002006-06-26 02:48:02 +02004866 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
Willy Tarreaue9d87882010-01-27 11:28:42 +01004867 "%s %s %s\r\n", args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
Willy Tarreaubaaee002006-06-26 02:48:02 +02004868 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004869 if (alertif_too_many_args_idx(3, 1, file, linenum, args, &err_code))
4870 goto out;
Willy Tarreauf3c69202006-07-09 16:42:34 +02004871 }
4872 else if (!strcmp(args[1], "ssl-hello-chk")) {
4873 /* use SSLv3 CLIENT HELLO to check servers' health */
Willy Tarreau13943ab2006-12-31 00:24:10 +01004874 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02004875 err_code |= ERR_WARN;
Willy Tarreau13943ab2006-12-31 00:24:10 +01004876
Willy Tarreaua534fea2008-08-03 12:19:50 +02004877 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004878 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004879 curproxy->options2 &= ~PR_O2_CHK_ANY;
Willy Tarreau07a54902010-03-29 18:33:29 +02004880 curproxy->options2 |= PR_O2_SSL3_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02004881
4882 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4883 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02004884 }
Willy Tarreau23677902007-05-08 23:50:35 +02004885 else if (!strcmp(args[1], "smtpchk")) {
4886 /* use SMTP request to check servers' health */
Willy Tarreaua534fea2008-08-03 12:19:50 +02004887 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004888 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004889 curproxy->options2 &= ~PR_O2_CHK_ANY;
4890 curproxy->options2 |= PR_O2_SMTP_CHK;
Willy Tarreau23677902007-05-08 23:50:35 +02004891
4892 if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
4893 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4894 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4895 } else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
4896 if (!strcmp(args[2], "EHLO") || !strcmp(args[2], "HELO")) {
4897 int reqlen = strlen(args[2]) + strlen(args[3]) + strlen(" \r\n") + 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004898 curproxy->check_req = malloc(reqlen);
Willy Tarreau23677902007-05-08 23:50:35 +02004899 curproxy->check_len = snprintf(curproxy->check_req, reqlen,
4900 "%s %s\r\n", args[2], args[3]); /* HELO hostname */
4901 } else {
4902 /* this just hits the default for now, but you could potentially expand it to allow for other stuff
4903 though, it's unlikely you'd want to send anything other than an EHLO or HELO */
4904 curproxy->check_req = strdup(DEF_SMTP_CHECK_REQ); /* default request */
4905 curproxy->check_len = strlen(DEF_SMTP_CHECK_REQ);
4906 }
4907 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004908 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4909 goto out;
Willy Tarreau23677902007-05-08 23:50:35 +02004910 }
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004911 else if (!strcmp(args[1], "pgsql-check")) {
4912 /* use PostgreSQL request to check servers' health */
4913 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4914 err_code |= ERR_WARN;
4915
4916 free(curproxy->check_req);
4917 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004918 curproxy->options2 &= ~PR_O2_CHK_ANY;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004919 curproxy->options2 |= PR_O2_PGSQL_CHK;
4920
4921 if (*(args[2])) {
4922 int cur_arg = 2;
4923
4924 while (*(args[cur_arg])) {
4925 if (strcmp(args[cur_arg], "user") == 0) {
4926 char * packet;
4927 uint32_t packet_len;
4928 uint32_t pv;
4929
4930 /* suboption header - needs additional argument for it */
4931 if (*(args[cur_arg+1]) == 0) {
4932 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
4933 file, linenum, args[0], args[1], args[cur_arg]);
4934 err_code |= ERR_ALERT | ERR_FATAL;
4935 goto out;
4936 }
4937
4938 /* uint32_t + uint32_t + strlen("user")+1 + strlen(username)+1 + 1 */
4939 packet_len = 4 + 4 + 5 + strlen(args[cur_arg + 1])+1 +1;
4940 pv = htonl(0x30000); /* protocol version 3.0 */
4941
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004942 packet = calloc(1, packet_len);
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004943
4944 memcpy(packet + 4, &pv, 4);
4945
4946 /* copy "user" */
4947 memcpy(packet + 8, "user", 4);
4948
4949 /* copy username */
4950 memcpy(packet + 13, args[cur_arg+1], strlen(args[cur_arg+1]));
4951
4952 free(curproxy->check_req);
4953 curproxy->check_req = packet;
4954 curproxy->check_len = packet_len;
4955
4956 packet_len = htonl(packet_len);
4957 memcpy(packet, &packet_len, 4);
4958 cur_arg += 2;
4959 } else {
4960 /* unknown suboption - catchall */
4961 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
4962 file, linenum, args[0], args[1]);
4963 err_code |= ERR_ALERT | ERR_FATAL;
4964 goto out;
4965 }
4966 } /* end while loop */
4967 }
William Lallemanddf1425a2015-04-28 20:17:49 +02004968 if (alertif_too_many_args_idx(2, 1, file, linenum, args, &err_code))
4969 goto out;
Rauf Kuliyev38b41562011-01-04 15:14:13 +01004970 }
4971
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004972 else if (!strcmp(args[1], "redis-check")) {
4973 /* use REDIS PING request to check servers' health */
4974 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4975 err_code |= ERR_WARN;
4976
4977 free(curproxy->check_req);
4978 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004979 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004980 curproxy->options2 |= PR_O2_REDIS_CHK;
4981
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02004982 curproxy->check_req = malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004983 memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ, sizeof(DEF_REDIS_CHECK_REQ) - 1);
4984 curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02004985
4986 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
4987 goto out;
Hervé COMMOWICKec032d62011-08-05 16:23:48 +02004988 }
4989
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004990 else if (!strcmp(args[1], "mysql-check")) {
4991 /* use MYSQL request to check servers' health */
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004992 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
4993 err_code |= ERR_WARN;
4994
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004995 free(curproxy->check_req);
Willy Tarreau54f6a582010-02-01 16:31:14 +01004996 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02004997 curproxy->options2 &= ~PR_O2_CHK_ANY;
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01004998 curproxy->options2 |= PR_O2_MYSQL_CHK;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02004999
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005000 /* This is an example of a MySQL >=4.0 client Authentication packet kindly provided by Cyril Bonte.
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005001 * const char mysql40_client_auth_pkt[] = {
5002 * "\x0e\x00\x00" // packet length
5003 * "\x01" // packet number
5004 * "\x00\x00" // client capabilities
5005 * "\x00\x00\x01" // max packet
5006 * "haproxy\x00" // username (null terminated string)
5007 * "\x00" // filler (always 0x00)
5008 * "\x01\x00\x00" // packet length
5009 * "\x00" // packet number
5010 * "\x01" // COM_QUIT command
5011 * };
5012 */
5013
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005014 /* This is an example of a MySQL >=4.1 client Authentication packet provided by Nenad Merdanovic.
5015 * const char mysql41_client_auth_pkt[] = {
5016 * "\x0e\x00\x00\" // packet length
5017 * "\x01" // packet number
5018 * "\x00\x00\x00\x00" // client capabilities
5019 * "\x00\x00\x00\x01" // max packet
5020 * "\x21" // character set (UTF-8)
5021 * char[23] // All zeroes
5022 * "haproxy\x00" // username (null terminated string)
5023 * "\x00" // filler (always 0x00)
5024 * "\x01\x00\x00" // packet length
5025 * "\x00" // packet number
5026 * "\x01" // COM_QUIT command
5027 * };
5028 */
5029
5030
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005031 if (*(args[2])) {
5032 int cur_arg = 2;
5033
5034 while (*(args[cur_arg])) {
5035 if (strcmp(args[cur_arg], "user") == 0) {
5036 char *mysqluser;
5037 int packetlen, reqlen, userlen;
5038
5039 /* suboption header - needs additional argument for it */
5040 if (*(args[cur_arg+1]) == 0) {
5041 Alert("parsing [%s:%d] : '%s %s %s' expects <username> as argument.\n",
5042 file, linenum, args[0], args[1], args[cur_arg]);
5043 err_code |= ERR_ALERT | ERR_FATAL;
5044 goto out;
5045 }
5046 mysqluser = args[cur_arg + 1];
5047 userlen = strlen(mysqluser);
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005048
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005049 if (*(args[cur_arg+2])) {
5050 if (!strcmp(args[cur_arg+2], "post-41")) {
5051 packetlen = userlen + 7 + 27;
5052 reqlen = packetlen + 9;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005053
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005054 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005055 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005056 curproxy->check_len = reqlen;
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005057
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005058 snprintf(curproxy->check_req, 4, "%c%c%c",
5059 ((unsigned char) packetlen & 0xff),
5060 ((unsigned char) (packetlen >> 8) & 0xff),
5061 ((unsigned char) (packetlen >> 16) & 0xff));
5062
5063 curproxy->check_req[3] = 1;
5064 curproxy->check_req[5] = 130;
5065 curproxy->check_req[11] = 1;
5066 curproxy->check_req[12] = 33;
5067 memcpy(&curproxy->check_req[36], mysqluser, userlen);
5068 curproxy->check_req[36 + userlen + 1 + 1] = 1;
5069 curproxy->check_req[36 + userlen + 1 + 1 + 4] = 1;
5070 cur_arg += 3;
5071 } else {
5072 Alert("parsing [%s:%d] : keyword '%s' only supports option 'post-41'.\n", file, linenum, args[cur_arg+2]);
5073 err_code |= ERR_ALERT | ERR_FATAL;
5074 goto out;
5075 }
5076 } else {
5077 packetlen = userlen + 7;
5078 reqlen = packetlen + 9;
5079
5080 free(curproxy->check_req);
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005081 curproxy->check_req = calloc(1, reqlen);
Nenad Merdanovic6639a7c2014-05-30 14:26:32 +02005082 curproxy->check_len = reqlen;
5083
5084 snprintf(curproxy->check_req, 4, "%c%c%c",
5085 ((unsigned char) packetlen & 0xff),
5086 ((unsigned char) (packetlen >> 8) & 0xff),
5087 ((unsigned char) (packetlen >> 16) & 0xff));
5088
5089 curproxy->check_req[3] = 1;
5090 curproxy->check_req[5] = 128;
5091 curproxy->check_req[8] = 1;
5092 memcpy(&curproxy->check_req[9], mysqluser, userlen);
5093 curproxy->check_req[9 + userlen + 1 + 1] = 1;
5094 curproxy->check_req[9 + userlen + 1 + 1 + 4] = 1;
5095 cur_arg += 2;
5096 }
Hervé COMMOWICK8776f1b2010-10-18 15:58:36 +02005097 } else {
5098 /* unknown suboption - catchall */
5099 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'user'.\n",
5100 file, linenum, args[0], args[1]);
5101 err_code |= ERR_ALERT | ERR_FATAL;
5102 goto out;
5103 }
5104 } /* end while loop */
5105 }
Hervé COMMOWICK698ae002010-01-12 09:25:13 +01005106 }
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005107 else if (!strcmp(args[1], "ldap-check")) {
5108 /* use LDAP request to check servers' health */
5109 free(curproxy->check_req);
5110 curproxy->check_req = NULL;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005111 curproxy->options2 &= ~PR_O2_CHK_ANY;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005112 curproxy->options2 |= PR_O2_LDAP_CHK;
5113
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005114 curproxy->check_req = malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005115 memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ, sizeof(DEF_LDAP_CHECK_REQ) - 1);
5116 curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
William Lallemanddf1425a2015-04-28 20:17:49 +02005117 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5118 goto out;
Gabor Lekenyb4c81e42010-09-29 18:17:05 +02005119 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005120 else if (!strcmp(args[1], "tcp-check")) {
5121 /* use raw TCPCHK send/expect to check servers' health */
5122 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[1], NULL))
5123 err_code |= ERR_WARN;
5124
5125 free(curproxy->check_req);
5126 curproxy->check_req = NULL;
5127 curproxy->options2 &= ~PR_O2_CHK_ANY;
5128 curproxy->options2 |= PR_O2_TCPCHK_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005129 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5130 goto out;
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005131 }
Simon Horman98637e52014-06-20 12:30:16 +09005132 else if (!strcmp(args[1], "external-check")) {
5133 /* excute an external command to check servers' health */
5134 free(curproxy->check_req);
5135 curproxy->check_req = NULL;
5136 curproxy->options2 &= ~PR_O2_CHK_ANY;
5137 curproxy->options2 |= PR_O2_EXT_CHK;
William Lallemanddf1425a2015-04-28 20:17:49 +02005138 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5139 goto out;
Simon Horman98637e52014-06-20 12:30:16 +09005140 }
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005141 else if (!strcmp(args[1], "forwardfor")) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005142 int cur_arg;
5143
5144 /* insert x-forwarded-for field, but not for the IP address listed as an except.
5145 * set default options (ie: bitfield, header name, etc)
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005146 */
Ross Westaf72a1d2008-08-03 10:51:45 +02005147
Willy Tarreau87cf5142011-08-19 22:57:24 +02005148 curproxy->options |= PR_O_FWDFOR | PR_O_FF_ALWAYS;
Ross Westaf72a1d2008-08-03 10:51:45 +02005149
5150 free(curproxy->fwdfor_hdr_name);
5151 curproxy->fwdfor_hdr_name = strdup(DEF_XFORWARDFOR_HDR);
5152 curproxy->fwdfor_hdr_len = strlen(DEF_XFORWARDFOR_HDR);
5153
5154 /* loop to go through arguments - start at 2, since 0+1 = "option" "forwardfor" */
5155 cur_arg = 2;
5156 while (*(args[cur_arg])) {
5157 if (!strcmp(args[cur_arg], "except")) {
5158 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005159 if (!*(args[cur_arg+1]) || !str2net(args[cur_arg+1], 1, &curproxy->except_net, &curproxy->except_mask)) {
Ross Westaf72a1d2008-08-03 10:51:45 +02005160 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5161 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005162 err_code |= ERR_ALERT | ERR_FATAL;
5163 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005164 }
5165 /* flush useless bits */
5166 curproxy->except_net.s_addr &= curproxy->except_mask.s_addr;
Ross Westaf72a1d2008-08-03 10:51:45 +02005167 cur_arg += 2;
5168 } else if (!strcmp(args[cur_arg], "header")) {
5169 /* suboption header - needs additional argument for it */
5170 if (*(args[cur_arg+1]) == 0) {
5171 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5172 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005173 err_code |= ERR_ALERT | ERR_FATAL;
5174 goto out;
Ross Westaf72a1d2008-08-03 10:51:45 +02005175 }
5176 free(curproxy->fwdfor_hdr_name);
5177 curproxy->fwdfor_hdr_name = strdup(args[cur_arg+1]);
5178 curproxy->fwdfor_hdr_len = strlen(curproxy->fwdfor_hdr_name);
5179 cur_arg += 2;
Willy Tarreau87cf5142011-08-19 22:57:24 +02005180 } else if (!strcmp(args[cur_arg], "if-none")) {
5181 curproxy->options &= ~PR_O_FF_ALWAYS;
5182 cur_arg += 1;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005183 } else {
Ross Westaf72a1d2008-08-03 10:51:45 +02005184 /* unknown suboption - catchall */
Willy Tarreau87cf5142011-08-19 22:57:24 +02005185 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except', 'header' and 'if-none'.\n",
Ross Westaf72a1d2008-08-03 10:51:45 +02005186 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005187 err_code |= ERR_ALERT | ERR_FATAL;
5188 goto out;
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005189 }
Ross Westaf72a1d2008-08-03 10:51:45 +02005190 } /* end while loop */
Willy Tarreau7ac51f62007-03-25 16:00:04 +02005191 }
Maik Broemme2850cb42009-04-17 18:53:21 +02005192 else if (!strcmp(args[1], "originalto")) {
5193 int cur_arg;
5194
5195 /* insert x-original-to field, but not for the IP address listed as an except.
5196 * set default options (ie: bitfield, header name, etc)
5197 */
5198
5199 curproxy->options |= PR_O_ORGTO;
5200
5201 free(curproxy->orgto_hdr_name);
5202 curproxy->orgto_hdr_name = strdup(DEF_XORIGINALTO_HDR);
5203 curproxy->orgto_hdr_len = strlen(DEF_XORIGINALTO_HDR);
5204
Willy Tarreau87cf5142011-08-19 22:57:24 +02005205 /* loop to go through arguments - start at 2, since 0+1 = "option" "originalto" */
Maik Broemme2850cb42009-04-17 18:53:21 +02005206 cur_arg = 2;
5207 while (*(args[cur_arg])) {
5208 if (!strcmp(args[cur_arg], "except")) {
5209 /* suboption except - needs additional argument for it */
Thierry FOURNIERfc7ac7b2014-02-11 15:23:04 +01005210 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 +02005211 Alert("parsing [%s:%d] : '%s %s %s' expects <address>[/mask] as argument.\n",
5212 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005213 err_code |= ERR_ALERT | ERR_FATAL;
5214 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005215 }
5216 /* flush useless bits */
5217 curproxy->except_to.s_addr &= curproxy->except_mask_to.s_addr;
5218 cur_arg += 2;
5219 } else if (!strcmp(args[cur_arg], "header")) {
5220 /* suboption header - needs additional argument for it */
5221 if (*(args[cur_arg+1]) == 0) {
5222 Alert("parsing [%s:%d] : '%s %s %s' expects <header_name> as argument.\n",
5223 file, linenum, args[0], args[1], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02005224 err_code |= ERR_ALERT | ERR_FATAL;
5225 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005226 }
5227 free(curproxy->orgto_hdr_name);
5228 curproxy->orgto_hdr_name = strdup(args[cur_arg+1]);
5229 curproxy->orgto_hdr_len = strlen(curproxy->orgto_hdr_name);
5230 cur_arg += 2;
5231 } else {
5232 /* unknown suboption - catchall */
5233 Alert("parsing [%s:%d] : '%s %s' only supports optional values: 'except' and 'header'.\n",
5234 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005235 err_code |= ERR_ALERT | ERR_FATAL;
5236 goto out;
Maik Broemme2850cb42009-04-17 18:53:21 +02005237 }
5238 } /* end while loop */
5239 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005240 else {
5241 Alert("parsing [%s:%d] : unknown option '%s'.\n", file, linenum, args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005242 err_code |= ERR_ALERT | ERR_FATAL;
5243 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005244 }
Willy Tarreau93893792009-07-23 13:19:11 +02005245 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005246 }
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005247 else if (!strcmp(args[0], "default_backend")) {
5248 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005249 err_code |= ERR_WARN;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005250
5251 if (*(args[1]) == 0) {
5252 Alert("parsing [%s:%d] : '%s' expects a backend name.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005253 err_code |= ERR_ALERT | ERR_FATAL;
5254 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005255 }
Willy Tarreaua534fea2008-08-03 12:19:50 +02005256 free(curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005257 curproxy->defbe.name = strdup(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005258
5259 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5260 goto out;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01005261 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005262 else if (!strcmp(args[0], "redispatch") || !strcmp(args[0], "redisp")) {
Willy Tarreau977b8e42006-12-29 14:19:17 +01005263 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005264 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005265
Willy Tarreaua3c504c2014-04-28 22:37:32 +02005266 if (!already_warned(WARN_REDISPATCH_DEPRECATED))
5267 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 +01005268 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005269 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005270 /* enable reconnections to dispatch */
5271 curproxy->options |= PR_O_REDISP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005272
5273 if (alertif_too_many_args_idx(1, 0, file, linenum, args, &err_code))
5274 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005275 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005276 else if (!strcmp(args[0], "http-reuse")) {
5277 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5278 err_code |= ERR_WARN;
5279
5280 if (strcmp(args[1], "never") == 0) {
5281 /* enable a graceful server shutdown on an HTTP 404 response */
5282 curproxy->options &= ~PR_O_REUSE_MASK;
5283 curproxy->options |= PR_O_REUSE_NEVR;
5284 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5285 goto out;
5286 }
Willy Tarreau161d45f2015-08-05 16:02:46 +02005287 else if (strcmp(args[1], "safe") == 0) {
5288 /* enable a graceful server shutdown on an HTTP 404 response */
5289 curproxy->options &= ~PR_O_REUSE_MASK;
5290 curproxy->options |= PR_O_REUSE_SAFE;
5291 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5292 goto out;
5293 }
Willy Tarreau449d74a2015-08-05 17:16:33 +02005294 else if (strcmp(args[1], "aggressive") == 0) {
5295 curproxy->options &= ~PR_O_REUSE_MASK;
5296 curproxy->options |= PR_O_REUSE_AGGR;
5297 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5298 goto out;
5299 }
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005300 else if (strcmp(args[1], "always") == 0) {
5301 /* enable a graceful server shutdown on an HTTP 404 response */
5302 curproxy->options &= ~PR_O_REUSE_MASK;
5303 curproxy->options |= PR_O_REUSE_ALWS;
5304 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5305 goto out;
5306 }
5307 else {
Willy Tarreau449d74a2015-08-05 17:16:33 +02005308 Alert("parsing [%s:%d] : '%s' only supports 'never', 'safe', 'aggressive', 'always'.\n", file, linenum, args[0]);
Willy Tarreaud8fecee2015-08-05 14:12:31 +02005309 err_code |= ERR_ALERT | ERR_FATAL;
5310 goto out;
5311 }
5312 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005313 else if (!strcmp(args[0], "http-check")) {
5314 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005315 err_code |= ERR_WARN;
Willy Tarreau48494c02007-11-30 10:41:39 +01005316
5317 if (strcmp(args[1], "disable-on-404") == 0) {
5318 /* enable a graceful server shutdown on an HTTP 404 response */
5319 curproxy->options |= PR_O_DISABLE404;
William Lallemanddf1425a2015-04-28 20:17:49 +02005320 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5321 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005322 }
Willy Tarreauef781042010-01-27 11:53:01 +01005323 else if (strcmp(args[1], "send-state") == 0) {
5324 /* enable emission of the apparent state of a server in HTTP checks */
5325 curproxy->options2 |= PR_O2_CHK_SNDST;
William Lallemanddf1425a2015-04-28 20:17:49 +02005326 if (alertif_too_many_args_idx(0, 1, file, linenum, args, &err_code))
5327 goto out;
Willy Tarreauef781042010-01-27 11:53:01 +01005328 }
Willy Tarreaubd741542010-03-16 18:46:54 +01005329 else if (strcmp(args[1], "expect") == 0) {
5330 const char *ptr_arg;
5331 int cur_arg;
5332
5333 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5334 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5335 err_code |= ERR_ALERT | ERR_FATAL;
5336 goto out;
5337 }
5338
5339 cur_arg = 2;
5340 /* consider exclamation marks, sole or at the beginning of a word */
5341 while (*(ptr_arg = args[cur_arg])) {
5342 while (*ptr_arg == '!') {
5343 curproxy->options2 ^= PR_O2_EXP_INV;
5344 ptr_arg++;
5345 }
5346 if (*ptr_arg)
5347 break;
5348 cur_arg++;
5349 }
5350 /* now ptr_arg points to the beginning of a word past any possible
5351 * exclamation mark, and cur_arg is the argument which holds this word.
5352 */
5353 if (strcmp(ptr_arg, "status") == 0) {
5354 if (!*(args[cur_arg + 1])) {
5355 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5356 file, linenum, args[0], args[1], ptr_arg);
5357 err_code |= ERR_ALERT | ERR_FATAL;
5358 goto out;
5359 }
5360 curproxy->options2 |= PR_O2_EXP_STS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005361 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005362 curproxy->expect_str = strdup(args[cur_arg + 1]);
5363 }
5364 else if (strcmp(ptr_arg, "string") == 0) {
5365 if (!*(args[cur_arg + 1])) {
5366 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5367 file, linenum, args[0], args[1], ptr_arg);
5368 err_code |= ERR_ALERT | ERR_FATAL;
5369 goto out;
5370 }
5371 curproxy->options2 |= PR_O2_EXP_STR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005372 free(curproxy->expect_str);
Willy Tarreaubd741542010-03-16 18:46:54 +01005373 curproxy->expect_str = strdup(args[cur_arg + 1]);
5374 }
5375 else if (strcmp(ptr_arg, "rstatus") == 0) {
5376 if (!*(args[cur_arg + 1])) {
5377 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5378 file, linenum, args[0], args[1], ptr_arg);
5379 err_code |= ERR_ALERT | ERR_FATAL;
5380 goto out;
5381 }
5382 curproxy->options2 |= PR_O2_EXP_RSTS;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005383 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005384 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005385 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005386 free(curproxy->expect_regex);
5387 curproxy->expect_regex = NULL;
5388 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005389 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005390 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5391 error = NULL;
5392 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5393 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5394 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5395 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005396 err_code |= ERR_ALERT | ERR_FATAL;
5397 goto out;
5398 }
5399 }
5400 else if (strcmp(ptr_arg, "rstring") == 0) {
5401 if (!*(args[cur_arg + 1])) {
5402 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5403 file, linenum, args[0], args[1], ptr_arg);
5404 err_code |= ERR_ALERT | ERR_FATAL;
5405 goto out;
5406 }
5407 curproxy->options2 |= PR_O2_EXP_RSTR;
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005408 free(curproxy->expect_str);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005409 if (curproxy->expect_regex) {
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005410 regex_free(curproxy->expect_regex);
Thierry FOURNIER148f4082014-06-11 14:45:31 +02005411 free(curproxy->expect_regex);
5412 curproxy->expect_regex = NULL;
5413 }
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005414 curproxy->expect_str = strdup(args[cur_arg + 1]);
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005415 curproxy->expect_regex = calloc(1, sizeof(*curproxy->expect_regex));
5416 error = NULL;
5417 if (!regex_comp(args[cur_arg + 1], curproxy->expect_regex, 1, 1, &error)) {
5418 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5419 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5420 free(error);
Willy Tarreaubd741542010-03-16 18:46:54 +01005421 err_code |= ERR_ALERT | ERR_FATAL;
5422 goto out;
5423 }
5424 }
5425 else {
5426 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'status', 'string', 'rstatus', 'rstring', found '%s'.\n",
5427 file, linenum, args[0], args[1], ptr_arg);
5428 err_code |= ERR_ALERT | ERR_FATAL;
5429 goto out;
5430 }
5431 }
Willy Tarreau48494c02007-11-30 10:41:39 +01005432 else {
Willy Tarreau1ee51a62011-08-19 20:04:17 +02005433 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 +02005434 err_code |= ERR_ALERT | ERR_FATAL;
5435 goto out;
Willy Tarreau48494c02007-11-30 10:41:39 +01005436 }
5437 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005438 else if (!strcmp(args[0], "tcp-check")) {
5439 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5440 err_code |= ERR_WARN;
5441
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005442 if (strcmp(args[1], "comment") == 0) {
5443 int cur_arg;
5444 struct tcpcheck_rule *tcpcheck;
5445
5446 cur_arg = 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005447 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005448 tcpcheck->action = TCPCHK_ACT_COMMENT;
5449
5450 if (!*args[cur_arg + 1]) {
5451 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5452 file, linenum, args[cur_arg]);
5453 err_code |= ERR_ALERT | ERR_FATAL;
5454 goto out;
5455 }
5456
5457 tcpcheck->comment = strdup(args[cur_arg + 1]);
5458
5459 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
William Lallemanddf1425a2015-04-28 20:17:49 +02005460 if (alertif_too_many_args_idx(1, 1, file, linenum, args, &err_code))
5461 goto out;
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005462 }
5463 else if (strcmp(args[1], "connect") == 0) {
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005464 const char *ptr_arg;
5465 int cur_arg;
5466 struct tcpcheck_rule *tcpcheck;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005467
5468 /* check if first rule is also a 'connect' action */
Willy Tarreau5581c272015-05-13 12:24:53 +02005469 tcpcheck = LIST_NEXT(&curproxy->tcpcheck_rules, struct tcpcheck_rule *, list);
5470 while (&tcpcheck->list != &curproxy->tcpcheck_rules &&
5471 tcpcheck->action == TCPCHK_ACT_COMMENT) {
5472 tcpcheck = LIST_NEXT(&tcpcheck->list, struct tcpcheck_rule *, list);
5473 }
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005474
Willy Tarreau5581c272015-05-13 12:24:53 +02005475 if (&tcpcheck->list != &curproxy->tcpcheck_rules
5476 && tcpcheck->action != TCPCHK_ACT_CONNECT) {
5477 Alert("parsing [%s:%d] : first step MUST also be a 'connect' when there is a 'connect' step in the tcp-check ruleset.\n",
5478 file, linenum);
5479 err_code |= ERR_ALERT | ERR_FATAL;
5480 goto out;
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005481 }
5482
5483 cur_arg = 2;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005484 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005485 tcpcheck->action = TCPCHK_ACT_CONNECT;
5486
5487 /* parsing each parameters to fill up the rule */
5488 while (*(ptr_arg = args[cur_arg])) {
5489 /* tcp port */
5490 if (strcmp(args[cur_arg], "port") == 0) {
5491 if ( (atol(args[cur_arg + 1]) > 65535) ||
5492 (atol(args[cur_arg + 1]) < 1) ){
5493 Alert("parsing [%s:%d] : '%s %s %s' expects a valid TCP port (from range 1 to 65535), got %s.\n",
5494 file, linenum, args[0], args[1], "port", args[cur_arg + 1]);
5495 err_code |= ERR_ALERT | ERR_FATAL;
5496 goto out;
5497 }
5498 tcpcheck->port = atol(args[cur_arg + 1]);
5499 cur_arg += 2;
5500 }
5501 /* send proxy protocol */
5502 else if (strcmp(args[cur_arg], "send-proxy") == 0) {
5503 tcpcheck->conn_opts |= TCPCHK_OPT_SEND_PROXY;
5504 cur_arg++;
5505 }
5506#ifdef USE_OPENSSL
5507 else if (strcmp(args[cur_arg], "ssl") == 0) {
5508 curproxy->options |= PR_O_TCPCHK_SSL;
5509 tcpcheck->conn_opts |= TCPCHK_OPT_SSL;
5510 cur_arg++;
5511 }
5512#endif /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005513 /* comment for this tcpcheck line */
5514 else if (strcmp(args[cur_arg], "comment") == 0) {
5515 if (!*args[cur_arg + 1]) {
5516 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5517 file, linenum, args[cur_arg]);
5518 err_code |= ERR_ALERT | ERR_FATAL;
5519 goto out;
5520 }
5521 tcpcheck->comment = strdup(args[cur_arg + 1]);
5522 cur_arg += 2;
5523 }
Baptiste Assmann69e273f2013-12-11 00:52:19 +01005524 else {
5525#ifdef USE_OPENSSL
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005526 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 +01005527#else /* USE_OPENSSL */
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005528 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 +01005529#endif /* USE_OPENSSL */
5530 file, linenum, args[0], args[1], args[cur_arg]);
5531 err_code |= ERR_ALERT | ERR_FATAL;
5532 goto out;
5533 }
5534
5535 }
5536
5537 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5538 }
5539 else if (strcmp(args[1], "send") == 0) {
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005540 if (! *(args[2]) ) {
5541 /* SEND string expected */
5542 Alert("parsing [%s:%d] : '%s %s %s' expects <STRING> as argument.\n",
5543 file, linenum, args[0], args[1], args[2]);
5544 err_code |= ERR_ALERT | ERR_FATAL;
5545 goto out;
5546 } else {
5547 struct tcpcheck_rule *tcpcheck;
5548
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005549 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005550
5551 tcpcheck->action = TCPCHK_ACT_SEND;
5552 tcpcheck->string_len = strlen(args[2]);
5553 tcpcheck->string = strdup(args[2]);
5554 tcpcheck->expect_regex = NULL;
5555
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005556 /* comment for this tcpcheck line */
5557 if (strcmp(args[3], "comment") == 0) {
5558 if (!*args[4]) {
5559 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5560 file, linenum, args[3]);
5561 err_code |= ERR_ALERT | ERR_FATAL;
5562 goto out;
5563 }
5564 tcpcheck->comment = strdup(args[4]);
5565 }
5566
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005567 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5568 }
5569 }
5570 else if (strcmp(args[1], "send-binary") == 0) {
5571 if (! *(args[2]) ) {
5572 /* SEND binary string expected */
5573 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument.\n",
5574 file, linenum, args[0], args[1], args[2]);
5575 err_code |= ERR_ALERT | ERR_FATAL;
5576 goto out;
5577 } else {
5578 struct tcpcheck_rule *tcpcheck;
5579 char *err = NULL;
5580
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005581 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005582
5583 tcpcheck->action = TCPCHK_ACT_SEND;
5584 if (parse_binary(args[2], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5585 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5586 file, linenum, args[0], args[1], args[2], err);
5587 err_code |= ERR_ALERT | ERR_FATAL;
5588 goto out;
5589 }
5590 tcpcheck->expect_regex = NULL;
5591
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005592 /* comment for this tcpcheck line */
5593 if (strcmp(args[3], "comment") == 0) {
5594 if (!*args[4]) {
5595 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5596 file, linenum, args[3]);
5597 err_code |= ERR_ALERT | ERR_FATAL;
5598 goto out;
5599 }
5600 tcpcheck->comment = strdup(args[4]);
5601 }
5602
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005603 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5604 }
5605 }
5606 else if (strcmp(args[1], "expect") == 0) {
5607 const char *ptr_arg;
5608 int cur_arg;
5609 int inverse = 0;
5610
5611 if (curproxy->options2 & PR_O2_EXP_TYPE) {
5612 Alert("parsing [%s:%d] : '%s %s' already specified.\n", file, linenum, args[0], args[1]);
5613 err_code |= ERR_ALERT | ERR_FATAL;
5614 goto out;
5615 }
5616
5617 cur_arg = 2;
5618 /* consider exclamation marks, sole or at the beginning of a word */
5619 while (*(ptr_arg = args[cur_arg])) {
5620 while (*ptr_arg == '!') {
5621 inverse = !inverse;
5622 ptr_arg++;
5623 }
5624 if (*ptr_arg)
5625 break;
5626 cur_arg++;
5627 }
5628 /* now ptr_arg points to the beginning of a word past any possible
5629 * exclamation mark, and cur_arg is the argument which holds this word.
5630 */
5631 if (strcmp(ptr_arg, "binary") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005632 struct tcpcheck_rule *tcpcheck;
5633 char *err = NULL;
5634
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005635 if (!*(args[cur_arg + 1])) {
5636 Alert("parsing [%s:%d] : '%s %s %s' expects <binary string> as an argument.\n",
5637 file, linenum, args[0], args[1], ptr_arg);
5638 err_code |= ERR_ALERT | ERR_FATAL;
5639 goto out;
5640 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005641
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005642 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005643
5644 tcpcheck->action = TCPCHK_ACT_EXPECT;
5645 if (parse_binary(args[cur_arg + 1], &tcpcheck->string, &tcpcheck->string_len, &err) == 0) {
5646 Alert("parsing [%s:%d] : '%s %s %s' expects <BINARY STRING> as argument, but %s\n",
5647 file, linenum, args[0], args[1], args[2], err);
5648 err_code |= ERR_ALERT | ERR_FATAL;
5649 goto out;
5650 }
5651 tcpcheck->expect_regex = NULL;
5652 tcpcheck->inverse = inverse;
5653
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005654 /* tcpcheck comment */
5655 cur_arg += 2;
5656 if (strcmp(args[cur_arg], "comment") == 0) {
5657 if (!*args[cur_arg + 1]) {
5658 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5659 file, linenum, args[cur_arg + 1]);
5660 err_code |= ERR_ALERT | ERR_FATAL;
5661 goto out;
5662 }
5663 tcpcheck->comment = strdup(args[cur_arg + 1]);
5664 }
5665
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005666 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5667 }
5668 else if (strcmp(ptr_arg, "string") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005669 struct tcpcheck_rule *tcpcheck;
5670
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005671 if (!*(args[cur_arg + 1])) {
5672 Alert("parsing [%s:%d] : '%s %s %s' expects <string> as an argument.\n",
5673 file, linenum, args[0], args[1], ptr_arg);
5674 err_code |= ERR_ALERT | ERR_FATAL;
5675 goto out;
5676 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005677
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005678 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005679
5680 tcpcheck->action = TCPCHK_ACT_EXPECT;
5681 tcpcheck->string_len = strlen(args[cur_arg + 1]);
5682 tcpcheck->string = strdup(args[cur_arg + 1]);
5683 tcpcheck->expect_regex = NULL;
5684 tcpcheck->inverse = inverse;
5685
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005686 /* tcpcheck comment */
5687 cur_arg += 2;
5688 if (strcmp(args[cur_arg], "comment") == 0) {
5689 if (!*args[cur_arg + 1]) {
5690 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5691 file, linenum, args[cur_arg + 1]);
5692 err_code |= ERR_ALERT | ERR_FATAL;
5693 goto out;
5694 }
5695 tcpcheck->comment = strdup(args[cur_arg + 1]);
5696 }
5697
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005698 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5699 }
5700 else if (strcmp(ptr_arg, "rstring") == 0) {
Willy Tarreaue7acee72015-02-27 16:37:05 +01005701 struct tcpcheck_rule *tcpcheck;
5702
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005703 if (!*(args[cur_arg + 1])) {
5704 Alert("parsing [%s:%d] : '%s %s %s' expects <regex> as an argument.\n",
5705 file, linenum, args[0], args[1], ptr_arg);
5706 err_code |= ERR_ALERT | ERR_FATAL;
5707 goto out;
5708 }
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005709
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02005710 tcpcheck = calloc(1, sizeof(*tcpcheck));
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005711
5712 tcpcheck->action = TCPCHK_ACT_EXPECT;
5713 tcpcheck->string_len = 0;
5714 tcpcheck->string = NULL;
Thierry FOURNIER09af0d62014-06-18 11:35:54 +02005715 tcpcheck->expect_regex = calloc(1, sizeof(*tcpcheck->expect_regex));
5716 error = NULL;
5717 if (!regex_comp(args[cur_arg + 1], tcpcheck->expect_regex, 1, 1, &error)) {
5718 Alert("parsing [%s:%d] : '%s %s %s' : bad regular expression '%s': %s.\n",
5719 file, linenum, args[0], args[1], ptr_arg, args[cur_arg + 1], error);
5720 free(error);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005721 err_code |= ERR_ALERT | ERR_FATAL;
5722 goto out;
5723 }
5724 tcpcheck->inverse = inverse;
5725
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005726 /* tcpcheck comment */
5727 cur_arg += 2;
5728 if (strcmp(args[cur_arg], "comment") == 0) {
5729 if (!*args[cur_arg + 1]) {
5730 Alert("parsing [%s:%d] : '%s' expects a comment string.\n",
5731 file, linenum, args[cur_arg + 1]);
5732 err_code |= ERR_ALERT | ERR_FATAL;
5733 goto out;
5734 }
5735 tcpcheck->comment = strdup(args[cur_arg + 1]);
5736 }
5737
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005738 LIST_ADDQ(&curproxy->tcpcheck_rules, &tcpcheck->list);
5739 }
5740 else {
5741 Alert("parsing [%s:%d] : '%s %s' only supports [!] 'binary', 'string', 'rstring', found '%s'.\n",
5742 file, linenum, args[0], args[1], ptr_arg);
5743 err_code |= ERR_ALERT | ERR_FATAL;
5744 goto out;
5745 }
5746 }
5747 else {
Baptiste Assmann22b09d22015-05-01 08:03:04 +02005748 Alert("parsing [%s:%d] : '%s' only supports 'comment', 'connect', 'send' or 'expect'.\n", file, linenum, args[0]);
Baptiste Assmann5ecb77f2013-10-06 23:24:13 +02005749 err_code |= ERR_ALERT | ERR_FATAL;
5750 goto out;
5751 }
5752 }
Willy Tarreaub80c2302007-11-30 20:51:32 +01005753 else if (!strcmp(args[0], "monitor")) {
Willy Tarreaub099aca2008-10-12 17:26:37 +02005754 if (curproxy == &defproxy) {
5755 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005756 err_code |= ERR_ALERT | ERR_FATAL;
5757 goto out;
Willy Tarreaub099aca2008-10-12 17:26:37 +02005758 }
5759
Willy Tarreaub80c2302007-11-30 20:51:32 +01005760 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005761 err_code |= ERR_WARN;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005762
5763 if (strcmp(args[1], "fail") == 0) {
5764 /* add a condition to fail monitor requests */
Willy Tarreauef6494c2010-01-28 17:12:36 +01005765 if (strcmp(args[2], "if") != 0 && strcmp(args[2], "unless") != 0) {
Willy Tarreaub80c2302007-11-30 20:51:32 +01005766 Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
5767 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005768 err_code |= ERR_ALERT | ERR_FATAL;
5769 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005770 }
5771
Willy Tarreaub7451bb2012-04-27 12:38:15 +02005772 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args + 2, &errmsg)) == NULL) {
5773 Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition : %s.\n",
5774 file, linenum, args[0], args[1], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005775 err_code |= ERR_ALERT | ERR_FATAL;
5776 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005777 }
5778 LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
5779 }
5780 else {
5781 Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005782 err_code |= ERR_ALERT | ERR_FATAL;
5783 goto out;
Willy Tarreaub80c2302007-11-30 20:51:32 +01005784 }
5785 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005786#ifdef TPROXY
5787 else if (!strcmp(args[0], "transparent")) {
5788 /* enable transparent proxy connections */
5789 curproxy->options |= PR_O_TRANSP;
William Lallemanddf1425a2015-04-28 20:17:49 +02005790 if (alertif_too_many_args(0, file, linenum, args, &err_code))
5791 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005792 }
5793#endif
5794 else if (!strcmp(args[0], "maxconn")) { /* maxconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005795 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], " Maybe you want 'fullconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005796 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005797
Willy Tarreaubaaee002006-06-26 02:48:02 +02005798 if (*(args[1]) == 0) {
5799 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005800 err_code |= ERR_ALERT | ERR_FATAL;
5801 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005802 }
5803 curproxy->maxconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005804 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5805 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005806 }
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005807 else if (!strcmp(args[0], "backlog")) { /* backlog */
5808 if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005809 err_code |= ERR_WARN;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005810
5811 if (*(args[1]) == 0) {
5812 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005813 err_code |= ERR_ALERT | ERR_FATAL;
5814 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005815 }
5816 curproxy->backlog = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005817 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5818 goto out;
Willy Tarreauc73ce2b2008-01-06 10:55:10 +01005819 }
Willy Tarreau86034312006-12-29 00:10:33 +01005820 else if (!strcmp(args[0], "fullconn")) { /* fullconn */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005821 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], " Maybe you want 'maxconn' instead ?"))
Willy Tarreau93893792009-07-23 13:19:11 +02005822 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005823
Willy Tarreau86034312006-12-29 00:10:33 +01005824 if (*(args[1]) == 0) {
5825 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005826 err_code |= ERR_ALERT | ERR_FATAL;
5827 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005828 }
5829 curproxy->fullconn = atol(args[1]);
William Lallemanddf1425a2015-04-28 20:17:49 +02005830 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5831 goto out;
Willy Tarreau86034312006-12-29 00:10:33 +01005832 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005833 else if (!strcmp(args[0], "grace")) { /* grace time (ms) */
5834 if (*(args[1]) == 0) {
5835 Alert("parsing [%s:%d] : '%s' expects a time in milliseconds.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005836 err_code |= ERR_ALERT | ERR_FATAL;
5837 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005838 }
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005839 err = parse_time_err(args[1], &val, TIME_UNIT_MS);
5840 if (err) {
5841 Alert("parsing [%s:%d] : unexpected character '%c' in grace time.\n",
5842 file, linenum, *err);
Willy Tarreau93893792009-07-23 13:19:11 +02005843 err_code |= ERR_ALERT | ERR_FATAL;
5844 goto out;
Willy Tarreaub3f32f52007-12-02 22:15:14 +01005845 }
5846 curproxy->grace = val;
William Lallemanddf1425a2015-04-28 20:17:49 +02005847 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5848 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005849 }
5850 else if (!strcmp(args[0], "dispatch")) { /* dispatch address */
David du Colombier6f5ccb12011-03-10 22:26:24 +01005851 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005852 int port1, port2;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005853 struct protocol *proto;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005854
Willy Tarreaubaaee002006-06-26 02:48:02 +02005855 if (curproxy == &defproxy) {
5856 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02005857 err_code |= ERR_ALERT | ERR_FATAL;
5858 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005859 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01005860 else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005861 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005862
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02005863 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005864 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01005865 Alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005866 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005867 goto out;
5868 }
Willy Tarreauf3559bf2013-03-06 16:52:04 +01005869
5870 proto = protocol_by_family(sk->ss_family);
5871 if (!proto || !proto->connect) {
5872 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
5873 file, linenum, args[0], args[1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005874 err_code |= ERR_ALERT | ERR_FATAL;
5875 goto out;
5876 }
5877
5878 if (port1 != port2) {
5879 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'.\n",
5880 file, linenum, args[0], args[1]);
Willy Tarreau93893792009-07-23 13:19:11 +02005881 err_code |= ERR_ALERT | ERR_FATAL;
5882 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005883 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005884
5885 if (!port1) {
5886 Alert("parsing [%s:%d] : '%s' : missing port number in '%s', <addr:port> expected.\n",
5887 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01005888 err_code |= ERR_ALERT | ERR_FATAL;
5889 goto out;
5890 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01005891
William Lallemanddf1425a2015-04-28 20:17:49 +02005892 if (alertif_too_many_args(1, file, linenum, args, &err_code))
5893 goto out;
5894
Willy Tarreaud5191e72010-02-09 20:50:45 +01005895 curproxy->dispatch_addr = *sk;
Willy Tarreau1620ec32011-08-06 17:05:02 +02005896 curproxy->options |= PR_O_DISPATCH;
Willy Tarreaubaaee002006-06-26 02:48:02 +02005897 }
5898 else if (!strcmp(args[0], "balance")) { /* set balancing with optional algorithm */
Willy Tarreau977b8e42006-12-29 14:19:17 +01005899 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02005900 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01005901
Willy Tarreaua93c74b2012-05-08 18:14:39 +02005902 if (backend_parse_balance((const char **)args + 1, &errmsg, curproxy) < 0) {
5903 Alert("parsing [%s:%d] : %s %s\n", file, linenum, args[0], errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02005904 err_code |= ERR_ALERT | ERR_FATAL;
5905 goto out;
Willy Tarreau2fcb5002007-05-08 13:35:26 +02005906 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02005907 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005908 else if (!strcmp(args[0], "hash-type")) { /* set hashing method */
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005909 /**
5910 * The syntax for hash-type config element is
5911 * hash-type {map-based|consistent} [[<algo>] avalanche]
5912 *
5913 * The default hash function is sdbm for map-based and sdbm+avalanche for consistent.
5914 */
5915 curproxy->lbprm.algo &= ~(BE_LB_HASH_TYPE | BE_LB_HASH_FUNC | BE_LB_HASH_MOD);
Bhaskar98634f02013-10-29 23:30:51 -04005916
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005917 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
5918 err_code |= ERR_WARN;
5919
5920 if (strcmp(args[1], "consistent") == 0) { /* use consistent hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005921 curproxy->lbprm.algo |= BE_LB_HASH_CONS;
5922 }
5923 else if (strcmp(args[1], "map-based") == 0) { /* use map-based hashing */
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005924 curproxy->lbprm.algo |= BE_LB_HASH_MAP;
5925 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005926 else if (strcmp(args[1], "avalanche") == 0) {
5927 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]);
5928 err_code |= ERR_ALERT | ERR_FATAL;
5929 goto out;
Willy Tarreau798a39c2010-11-24 15:04:29 +01005930 }
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005931 else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005932 Alert("parsing [%s:%d] : '%s' only supports 'consistent' and 'map-based'.\n", file, linenum, args[0]);
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02005933 err_code |= ERR_ALERT | ERR_FATAL;
5934 goto out;
5935 }
Bhaskar98634f02013-10-29 23:30:51 -04005936
5937 /* set the hash function to use */
5938 if (!*args[2]) {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005939 /* the default algo is sdbm */
Bhaskar98634f02013-10-29 23:30:51 -04005940 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005941
5942 /* if consistent with no argument, then avalanche modifier is also applied */
5943 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS)
5944 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
Bhaskar98634f02013-10-29 23:30:51 -04005945 } else {
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005946 /* set the hash function */
5947 if (!strcmp(args[2], "sdbm")) {
5948 curproxy->lbprm.algo |= BE_LB_HFCN_SDBM;
5949 }
5950 else if (!strcmp(args[2], "djb2")) {
5951 curproxy->lbprm.algo |= BE_LB_HFCN_DJB2;
Willy Tarreau324f07f2015-01-20 19:44:50 +01005952 }
5953 else if (!strcmp(args[2], "wt6")) {
Willy Tarreaua0f42712013-11-14 14:30:35 +01005954 curproxy->lbprm.algo |= BE_LB_HFCN_WT6;
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005955 }
Willy Tarreau324f07f2015-01-20 19:44:50 +01005956 else if (!strcmp(args[2], "crc32")) {
5957 curproxy->lbprm.algo |= BE_LB_HFCN_CRC32;
5958 }
Bhaskar Maddalab6c0ac92013-11-05 11:54:02 -05005959 else {
Willy Tarreau324f07f2015-01-20 19:44:50 +01005960 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 -05005961 err_code |= ERR_ALERT | ERR_FATAL;
5962 goto out;
5963 }
5964
5965 /* set the hash modifier */
5966 if (!strcmp(args[3], "avalanche")) {
5967 curproxy->lbprm.algo |= BE_LB_HMOD_AVAL;
5968 }
5969 else if (*args[3]) {
5970 Alert("parsing [%s:%d] : '%s' only supports 'avalanche' as a modifier for hash functions.\n", file, linenum, args[0]);
5971 err_code |= ERR_ALERT | ERR_FATAL;
5972 goto out;
5973 }
Krzysztof Piotr Oledzkic6df0662010-01-05 16:38:49 +01005974 }
William Lallemanda73203e2012-03-12 12:48:57 +01005975 }
Andrew Rodlandb1f48e32016-10-25 12:49:05 -04005976 else if (strcmp(args[0], "hash-balance-factor") == 0) {
5977 if (*(args[1]) == 0) {
5978 Alert("parsing [%s:%d] : '%s' expects an integer argument.\n", file, linenum, args[0]);
5979 err_code |= ERR_ALERT | ERR_FATAL;
5980 goto out;
5981 }
5982 curproxy->lbprm.chash.balance_factor = atol(args[1]);
5983 if (curproxy->lbprm.chash.balance_factor != 0 && curproxy->lbprm.chash.balance_factor <= 100) {
5984 Alert("parsing [%s:%d] : '%s' must be 0 or greater than 100.\n", file, linenum, args[0]);
5985 err_code |= ERR_ALERT | ERR_FATAL;
5986 goto out;
5987 }
5988 }
William Lallemanda73203e2012-03-12 12:48:57 +01005989 else if (strcmp(args[0], "unique-id-format") == 0) {
5990 if (!*(args[1])) {
5991 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
5992 err_code |= ERR_ALERT | ERR_FATAL;
5993 goto out;
5994 }
William Lallemand3203ff42012-11-11 17:30:56 +01005995 if (*(args[2])) {
5996 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
5997 err_code |= ERR_ALERT | ERR_FATAL;
5998 goto out;
5999 }
Willy Tarreau62a61232013-04-12 18:13:46 +02006000 free(curproxy->conf.uniqueid_format_string);
6001 curproxy->conf.uniqueid_format_string = strdup(args[1]);
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006002
Willy Tarreau62a61232013-04-12 18:13:46 +02006003 free(curproxy->conf.uif_file);
6004 curproxy->conf.uif_file = strdup(curproxy->conf.args.file);
6005 curproxy->conf.uif_line = curproxy->conf.args.line;
William Lallemand723b73a2012-02-08 16:37:49 +01006006 }
William Lallemanda73203e2012-03-12 12:48:57 +01006007
6008 else if (strcmp(args[0], "unique-id-header") == 0) {
6009 if (!*(args[1])) {
6010 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6011 err_code |= ERR_ALERT | ERR_FATAL;
6012 goto out;
6013 }
6014 free(curproxy->header_unique_id);
6015 curproxy->header_unique_id = strdup(args[1]);
6016 }
6017
William Lallemand723b73a2012-02-08 16:37:49 +01006018 else if (strcmp(args[0], "log-format") == 0) {
6019 if (!*(args[1])) {
6020 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6021 err_code |= ERR_ALERT | ERR_FATAL;
6022 goto out;
6023 }
William Lallemand3203ff42012-11-11 17:30:56 +01006024 if (*(args[2])) {
6025 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6026 err_code |= ERR_ALERT | ERR_FATAL;
6027 goto out;
6028 }
Willy Tarreau196729e2012-05-31 19:30:26 +02006029
Willy Tarreau62a61232013-04-12 18:13:46 +02006030 if (curproxy->conf.logformat_string != default_http_log_format &&
6031 curproxy->conf.logformat_string != default_tcp_log_format &&
6032 curproxy->conf.logformat_string != clf_http_log_format)
6033 free(curproxy->conf.logformat_string);
6034 curproxy->conf.logformat_string = strdup(args[1]);
6035
6036 free(curproxy->conf.lfs_file);
6037 curproxy->conf.lfs_file = strdup(curproxy->conf.args.file);
6038 curproxy->conf.lfs_line = curproxy->conf.args.line;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02006039
6040 /* get a chance to improve log-format error reporting by
6041 * reporting the correct line-number when possible.
6042 */
6043 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6044 Warning("parsing [%s:%d] : backend '%s' : 'log-format' directive is ignored in backends.\n",
6045 file, linenum, curproxy->id);
6046 err_code |= ERR_WARN;
6047 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006048 }
Dragan Dosen0b85ece2015-09-25 19:17:44 +02006049 else if (!strcmp(args[0], "log-format-sd")) {
6050 if (!*(args[1])) {
6051 Alert("parsing [%s:%d] : %s expects an argument.\n", file, linenum, args[0]);
6052 err_code |= ERR_ALERT | ERR_FATAL;
6053 goto out;
6054 }
6055 if (*(args[2])) {
6056 Alert("parsing [%s:%d] : %s expects only one argument, don't forget to escape spaces!\n", file, linenum, args[0]);
6057 err_code |= ERR_ALERT | ERR_FATAL;
6058 goto out;
6059 }
6060
6061 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
6062 free(curproxy->conf.logformat_sd_string);
6063 curproxy->conf.logformat_sd_string = strdup(args[1]);
6064
6065 free(curproxy->conf.lfsd_file);
6066 curproxy->conf.lfsd_file = strdup(curproxy->conf.args.file);
6067 curproxy->conf.lfsd_line = curproxy->conf.args.line;
6068
6069 /* get a chance to improve log-format-sd error reporting by
6070 * reporting the correct line-number when possible.
6071 */
6072 if (curproxy != &defproxy && !(curproxy->cap & PR_CAP_FE)) {
6073 Warning("parsing [%s:%d] : backend '%s' : 'log-format-sd' directive is ignored in backends.\n",
6074 file, linenum, curproxy->id);
6075 err_code |= ERR_WARN;
6076 }
6077 }
Willy Tarreau094af4e2015-01-07 15:03:42 +01006078 else if (!strcmp(args[0], "log-tag")) { /* tag to report to syslog */
6079 if (*(args[1]) == 0) {
6080 Alert("parsing [%s:%d] : '%s' expects a tag for use in syslog.\n", file, linenum, args[0]);
6081 err_code |= ERR_ALERT | ERR_FATAL;
6082 goto out;
6083 }
Dragan Dosen43885c72015-10-01 13:18:13 +02006084 chunk_destroy(&curproxy->log_tag);
6085 chunk_initstr(&curproxy->log_tag, strdup(args[1]));
Willy Tarreau094af4e2015-01-07 15:03:42 +01006086 }
William Lallemand0f99e342011-10-12 17:50:54 +02006087 else if (!strcmp(args[0], "log") && kwm == KWM_NO) {
6088 /* delete previous herited or defined syslog servers */
6089 struct logsrv *back;
6090
6091 if (*(args[1]) != 0) {
6092 Alert("parsing [%s:%d]:%s : 'no log' does not expect arguments.\n", file, linenum, args[1]);
6093 err_code |= ERR_ALERT | ERR_FATAL;
6094 goto out;
6095 }
6096
William Lallemand723b73a2012-02-08 16:37:49 +01006097 list_for_each_entry_safe(tmplogsrv, back, &curproxy->logsrvs, list) {
6098 LIST_DEL(&tmplogsrv->list);
6099 free(tmplogsrv);
William Lallemand0f99e342011-10-12 17:50:54 +02006100 }
6101 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006102 else if (!strcmp(args[0], "log")) { /* syslog server address */
William Lallemand0f99e342011-10-12 17:50:54 +02006103 struct logsrv *logsrv;
6104
Willy Tarreaubaaee002006-06-26 02:48:02 +02006105 if (*(args[1]) && *(args[2]) == 0 && !strcmp(args[1], "global")) {
William Lallemand0f99e342011-10-12 17:50:54 +02006106 /* copy global.logrsvs linked list to the end of curproxy->logsrvs */
William Lallemand723b73a2012-02-08 16:37:49 +01006107 list_for_each_entry(tmplogsrv, &global.logsrvs, list) {
Vincent Bernat02779b62016-04-03 13:48:43 +02006108 struct logsrv *node = malloc(sizeof(*node));
William Lallemand723b73a2012-02-08 16:37:49 +01006109 memcpy(node, tmplogsrv, sizeof(struct logsrv));
William Lallemand0f99e342011-10-12 17:50:54 +02006110 LIST_INIT(&node->list);
6111 LIST_ADDQ(&curproxy->logsrvs, &node->list);
6112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006113 }
6114 else if (*(args[1]) && *(args[2])) {
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006115 struct sockaddr_storage *sk;
6116 int port1, port2;
Willy Tarreau18324f52014-06-27 18:10:07 +02006117 int arg = 0;
6118 int len = 0;
William Lallemand0f99e342011-10-12 17:50:54 +02006119
Vincent Bernat02779b62016-04-03 13:48:43 +02006120 logsrv = calloc(1, sizeof(*logsrv));
Willy Tarreaubaaee002006-06-26 02:48:02 +02006121
Willy Tarreau18324f52014-06-27 18:10:07 +02006122 /* just after the address, a length may be specified */
6123 if (strcmp(args[arg+2], "len") == 0) {
6124 len = atoi(args[arg+3]);
6125 if (len < 80 || len > 65535) {
6126 Alert("parsing [%s:%d] : invalid log length '%s', must be between 80 and 65535.\n",
6127 file, linenum, args[arg+3]);
6128 err_code |= ERR_ALERT | ERR_FATAL;
6129 goto out;
6130 }
6131 logsrv->maxlen = len;
6132
6133 /* skip these two args */
6134 arg += 2;
6135 }
6136 else
6137 logsrv->maxlen = MAX_SYSLOG_LEN;
6138
6139 if (logsrv->maxlen > global.max_syslog_len) {
6140 global.max_syslog_len = logsrv->maxlen;
Hubert Verstraete831962e2016-06-28 22:44:26 +02006141 logheader = my_realloc2(logheader, global.max_syslog_len + 1);
6142 logheader_rfc5424 = my_realloc2(logheader_rfc5424, global.max_syslog_len + 1);
6143 logline = my_realloc2(logline, global.max_syslog_len + 1);
6144 logline_rfc5424 = my_realloc2(logline_rfc5424, global.max_syslog_len + 1);
Willy Tarreau18324f52014-06-27 18:10:07 +02006145 }
6146
Dragan Dosen1322d092015-09-22 16:05:32 +02006147 /* after the length, a format may be specified */
6148 if (strcmp(args[arg+2], "format") == 0) {
6149 logsrv->format = get_log_format(args[arg+3]);
6150 if (logsrv->format < 0) {
6151 Alert("parsing [%s:%d] : unknown log format '%s'\n", file, linenum, args[arg+3]);
6152 err_code |= ERR_ALERT | ERR_FATAL;
6153 goto out;
6154 }
6155
6156 /* skip these two args */
6157 arg += 2;
6158 }
6159
William Lallemanddf1425a2015-04-28 20:17:49 +02006160 if (alertif_too_many_args_idx(3, arg + 1, file, linenum, args, &err_code))
6161 goto out;
6162
Willy Tarreau18324f52014-06-27 18:10:07 +02006163 logsrv->facility = get_log_facility(args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006164 if (logsrv->facility < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006165 Alert("parsing [%s:%d] : unknown log facility '%s'\n", file, linenum, args[arg+2]);
William Lallemand0f99e342011-10-12 17:50:54 +02006166 err_code |= ERR_ALERT | ERR_FATAL;
6167 goto out;
6168
Willy Tarreaubaaee002006-06-26 02:48:02 +02006169 }
6170
William Lallemand0f99e342011-10-12 17:50:54 +02006171 logsrv->level = 7; /* max syslog level = debug */
Willy Tarreau18324f52014-06-27 18:10:07 +02006172 if (*(args[arg+3])) {
6173 logsrv->level = get_log_level(args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006174 if (logsrv->level < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006175 Alert("parsing [%s:%d] : unknown optional log level '%s'\n", file, linenum, args[arg+3]);
William Lallemand0f99e342011-10-12 17:50:54 +02006176 err_code |= ERR_ALERT | ERR_FATAL;
6177 goto out;
6178
Willy Tarreaubaaee002006-06-26 02:48:02 +02006179 }
6180 }
6181
William Lallemand0f99e342011-10-12 17:50:54 +02006182 logsrv->minlvl = 0; /* limit syslog level to this level (emerg) */
Willy Tarreau18324f52014-06-27 18:10:07 +02006183 if (*(args[arg+4])) {
6184 logsrv->minlvl = get_log_level(args[arg+4]);
Willy Tarreauf7f057b2013-01-24 00:31:24 +01006185 if (logsrv->minlvl < 0) {
Willy Tarreau18324f52014-06-27 18:10:07 +02006186 Alert("parsing [%s:%d] : unknown optional minimum log level '%s'\n", file, linenum, args[arg+4]);
William Lallemand0f99e342011-10-12 17:50:54 +02006187 err_code |= ERR_ALERT | ERR_FATAL;
6188 goto out;
6189
Willy Tarreauf7edefa2009-05-10 17:20:05 +02006190 }
6191 }
6192
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006193 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006194 if (!sk) {
Willy Tarreau902636f2013-03-10 19:44:48 +01006195 Alert("parsing [%s:%d] : '%s': %s\n", file, linenum, args[0], errmsg);
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006196 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006197 goto out;
6198 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006199
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006200 logsrv->addr = *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006201
Willy Tarreau9b435bc2013-03-06 15:02:49 +01006202 if (sk->ss_family == AF_INET || sk->ss_family == AF_INET6) {
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006203 if (port1 != port2) {
6204 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6205 file, linenum, args[0], args[1]);
6206 err_code |= ERR_ALERT | ERR_FATAL;
6207 goto out;
6208 }
6209
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006210 if (!port1)
William Lallemand0f99e342011-10-12 17:50:54 +02006211 set_host_port(&logsrv->addr, SYSLOG_PORT);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006212 }
William Lallemand0f99e342011-10-12 17:50:54 +02006213
6214 LIST_ADDQ(&curproxy->logsrvs, &logsrv->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006215 }
6216 else {
6217 Alert("parsing [%s:%d] : 'log' expects either <address[:port]> and <facility> or 'global' as arguments.\n",
6218 file, linenum);
Willy Tarreau93893792009-07-23 13:19:11 +02006219 err_code |= ERR_ALERT | ERR_FATAL;
6220 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006221 }
6222 }
6223 else if (!strcmp(args[0], "source")) { /* address to which we bind when connecting */
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006224 int cur_arg;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006225 int port1, port2;
David du Colombier6f5ccb12011-03-10 22:26:24 +01006226 struct sockaddr_storage *sk;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006227 struct protocol *proto;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006228
Willy Tarreau977b8e42006-12-29 14:19:17 +01006229 if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006230 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006231
Willy Tarreaubaaee002006-06-26 02:48:02 +02006232 if (!*args[1]) {
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006233 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], and optionally '%s' <addr>, and '%s' <name>.\n",
6234 file, linenum, "source", "usesrc", "interface");
Willy Tarreau93893792009-07-23 13:19:11 +02006235 err_code |= ERR_ALERT | ERR_FATAL;
6236 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006237 }
Willy Tarreau368480c2009-03-01 08:27:21 +01006238
6239 /* we must first clear any optional default setting */
Willy Tarreauef9a3602012-12-08 22:29:20 +01006240 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6241 free(curproxy->conn_src.iface_name);
6242 curproxy->conn_src.iface_name = NULL;
6243 curproxy->conn_src.iface_len = 0;
Willy Tarreau368480c2009-03-01 08:27:21 +01006244
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006245 sk = str2sa_range(args[1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006246 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006247 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006248 file, linenum, args[0], args[1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006249 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006250 goto out;
6251 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006252
6253 proto = protocol_by_family(sk->ss_family);
6254 if (!proto || !proto->connect) {
6255 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006256 file, linenum, args[0], args[1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006257 err_code |= ERR_ALERT | ERR_FATAL;
6258 goto out;
6259 }
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006260
6261 if (port1 != port2) {
6262 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6263 file, linenum, args[0], args[1]);
6264 err_code |= ERR_ALERT | ERR_FATAL;
6265 goto out;
6266 }
6267
Willy Tarreauef9a3602012-12-08 22:29:20 +01006268 curproxy->conn_src.source_addr = *sk;
6269 curproxy->conn_src.opts |= CO_SRC_BIND;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006270
6271 cur_arg = 2;
6272 while (*(args[cur_arg])) {
6273 if (!strcmp(args[cur_arg], "usesrc")) { /* address to use outside */
Willy Tarreau29fbe512015-08-20 19:35:14 +02006274#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006275 if (!*args[cur_arg + 1]) {
6276 Alert("parsing [%s:%d] : '%s' expects <addr>[:<port>], 'client', or 'clientip' as argument.\n",
6277 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006278 err_code |= ERR_ALERT | ERR_FATAL;
6279 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006280 }
6281
6282 if (!strcmp(args[cur_arg + 1], "client")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006283 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6284 curproxy->conn_src.opts |= CO_SRC_TPROXY_CLI;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006285 } else if (!strcmp(args[cur_arg + 1], "clientip")) {
Willy Tarreauef9a3602012-12-08 22:29:20 +01006286 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6287 curproxy->conn_src.opts |= CO_SRC_TPROXY_CIP;
Willy Tarreaubce70882009-09-07 11:51:47 +02006288 } else if (!strncmp(args[cur_arg + 1], "hdr_ip(", 7)) {
6289 char *name, *end;
6290
6291 name = args[cur_arg+1] + 7;
6292 while (isspace(*name))
6293 name++;
6294
6295 end = name;
6296 while (*end && !isspace(*end) && *end != ',' && *end != ')')
6297 end++;
6298
Willy Tarreauef9a3602012-12-08 22:29:20 +01006299 curproxy->conn_src.opts &= ~CO_SRC_TPROXY_MASK;
6300 curproxy->conn_src.opts |= CO_SRC_TPROXY_DYN;
6301 curproxy->conn_src.bind_hdr_name = calloc(1, end - name + 1);
6302 curproxy->conn_src.bind_hdr_len = end - name;
6303 memcpy(curproxy->conn_src.bind_hdr_name, name, end - name);
6304 curproxy->conn_src.bind_hdr_name[end-name] = '\0';
6305 curproxy->conn_src.bind_hdr_occ = -1;
Willy Tarreaubce70882009-09-07 11:51:47 +02006306
6307 /* now look for an occurrence number */
6308 while (isspace(*end))
6309 end++;
6310 if (*end == ',') {
6311 end++;
6312 name = end;
6313 if (*end == '-')
6314 end++;
Willy Tarreau83d84cf2012-11-22 01:04:31 +01006315 while (isdigit((int)*end))
Willy Tarreaubce70882009-09-07 11:51:47 +02006316 end++;
Willy Tarreauef9a3602012-12-08 22:29:20 +01006317 curproxy->conn_src.bind_hdr_occ = strl2ic(name, end-name);
Willy Tarreaubce70882009-09-07 11:51:47 +02006318 }
6319
Willy Tarreauef9a3602012-12-08 22:29:20 +01006320 if (curproxy->conn_src.bind_hdr_occ < -MAX_HDR_HISTORY) {
Willy Tarreaubce70882009-09-07 11:51:47 +02006321 Alert("parsing [%s:%d] : usesrc hdr_ip(name,num) does not support negative"
6322 " occurrences values smaller than %d.\n",
6323 file, linenum, MAX_HDR_HISTORY);
6324 err_code |= ERR_ALERT | ERR_FATAL;
6325 goto out;
6326 }
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006327 } else {
Willy Tarreau902636f2013-03-10 19:44:48 +01006328 struct sockaddr_storage *sk;
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006329
Thierry FOURNIER7fe3be72015-09-26 20:03:36 +02006330 sk = str2sa_range(args[cur_arg + 1], &port1, &port2, &errmsg, NULL, NULL, 1);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006331 if (!sk) {
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006332 Alert("parsing [%s:%d] : '%s %s' : %s\n",
Willy Tarreau902636f2013-03-10 19:44:48 +01006333 file, linenum, args[cur_arg], args[cur_arg+1], errmsg);
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006334 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006335 goto out;
6336 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006337
6338 proto = protocol_by_family(sk->ss_family);
6339 if (!proto || !proto->connect) {
6340 Alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
6341 file, linenum, args[cur_arg], args[cur_arg+1]);
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006342 err_code |= ERR_ALERT | ERR_FATAL;
6343 goto out;
6344 }
Willy Tarreau2de5dae2013-03-10 18:51:54 +01006345
Willy Tarreau6d03cc32013-02-20 17:26:02 +01006346 if (port1 != port2) {
6347 Alert("parsing [%s:%d] : '%s' : port ranges and offsets are not allowed in '%s'\n",
6348 file, linenum, args[cur_arg], args[cur_arg + 1]);
Willy Tarreaud5191e72010-02-09 20:50:45 +01006349 err_code |= ERR_ALERT | ERR_FATAL;
6350 goto out;
6351 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006352 curproxy->conn_src.tproxy_addr = *sk;
6353 curproxy->conn_src.opts |= CO_SRC_TPROXY_ADDR;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006354 }
6355 global.last_checks |= LSTCHK_NETADM;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006356#else /* no TPROXY support */
6357 Alert("parsing [%s:%d] : '%s' not allowed here because support for TPROXY was not compiled in.\n",
Willy Tarreau77074d52006-11-12 23:57:19 +01006358 file, linenum, "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006359 err_code |= ERR_ALERT | ERR_FATAL;
6360 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006361#endif
6362 cur_arg += 2;
6363 continue;
Willy Tarreau77074d52006-11-12 23:57:19 +01006364 }
6365
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006366 if (!strcmp(args[cur_arg], "interface")) { /* specifically bind to this interface */
6367#ifdef SO_BINDTODEVICE
6368 if (!*args[cur_arg + 1]) {
6369 Alert("parsing [%s:%d] : '%s' : missing interface name.\n",
6370 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006371 err_code |= ERR_ALERT | ERR_FATAL;
6372 goto out;
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006373 }
Willy Tarreauef9a3602012-12-08 22:29:20 +01006374 free(curproxy->conn_src.iface_name);
6375 curproxy->conn_src.iface_name = strdup(args[cur_arg + 1]);
6376 curproxy->conn_src.iface_len = strlen(curproxy->conn_src.iface_name);
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006377 global.last_checks |= LSTCHK_NETADM;
6378#else
6379 Alert("parsing [%s:%d] : '%s' : '%s' option not implemented.\n",
6380 file, linenum, args[0], args[cur_arg]);
Willy Tarreau93893792009-07-23 13:19:11 +02006381 err_code |= ERR_ALERT | ERR_FATAL;
6382 goto out;
Willy Tarreau5b6995c2008-01-13 16:31:17 +01006383#endif
Willy Tarreaud53f96b2009-02-04 18:46:54 +01006384 cur_arg += 2;
6385 continue;
6386 }
6387 Alert("parsing [%s:%d] : '%s' only supports optional keywords '%s' and '%s'.\n",
Willy Tarreau3631d412012-09-25 16:31:00 +02006388 file, linenum, args[0], "interface", "usesrc");
Willy Tarreau93893792009-07-23 13:19:11 +02006389 err_code |= ERR_ALERT | ERR_FATAL;
6390 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006391 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006392 }
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006393 else if (!strcmp(args[0], "usesrc")) { /* address to use outside: needs "source" first */
6394 Alert("parsing [%s:%d] : '%s' only allowed after a '%s' statement.\n",
6395 file, linenum, "usesrc", "source");
Willy Tarreau93893792009-07-23 13:19:11 +02006396 err_code |= ERR_ALERT | ERR_FATAL;
6397 goto out;
Willy Tarreau8d9246d2007-03-24 12:47:24 +01006398 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006399 else if (!strcmp(args[0], "cliexp") || !strcmp(args[0], "reqrep")) { /* replace request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006400 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006401 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6402 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006403 err_code |= ERR_ALERT | ERR_FATAL;
6404 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006405 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006406
6407 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006408 SMP_OPT_DIR_REQ, ACT_REPLACE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006409 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006410 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006411 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006412 }
6413 else if (!strcmp(args[0], "reqdel")) { /* delete request header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006414 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006415 SMP_OPT_DIR_REQ, ACT_REMOVE, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006416 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006417 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006418 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006419 }
6420 else if (!strcmp(args[0], "reqdeny")) { /* deny a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006421 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006422 SMP_OPT_DIR_REQ, ACT_DENY, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006423 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006424 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006425 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006426 }
6427 else if (!strcmp(args[0], "reqpass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006428 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006429 SMP_OPT_DIR_REQ, ACT_PASS, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006430 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006431 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006432 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006433 }
6434 else if (!strcmp(args[0], "reqallow")) { /* allow a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006435 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006436 SMP_OPT_DIR_REQ, ACT_ALLOW, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006437 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006438 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006439 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006440 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006441 else if (!strcmp(args[0], "reqtarpit")) { /* tarpit a request if a header matches this regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006442 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006443 SMP_OPT_DIR_REQ, ACT_TARPIT, 0,
Willy Tarreau5321c422010-01-28 20:35:13 +01006444 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006445 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006446 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006447 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006448 else if (!strcmp(args[0], "reqirep")) { /* replace request header from a regex, ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006449 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006450 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6451 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006452 err_code |= ERR_ALERT | ERR_FATAL;
6453 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006454 }
Willy Tarreauade5ec42010-01-28 19:33:49 +01006455
6456 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006457 SMP_OPT_DIR_REQ, ACT_REPLACE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006458 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006459 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006460 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006461 }
6462 else if (!strcmp(args[0], "reqidel")) { /* delete request header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006463 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006464 SMP_OPT_DIR_REQ, ACT_REMOVE, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006465 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006466 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006467 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006468 }
6469 else if (!strcmp(args[0], "reqideny")) { /* deny a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006470 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006471 SMP_OPT_DIR_REQ, ACT_DENY, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006472 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006473 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006474 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006475 }
6476 else if (!strcmp(args[0], "reqipass")) { /* pass this header without allowing or denying the request */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006477 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006478 SMP_OPT_DIR_REQ, ACT_PASS, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006479 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006480 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006481 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006482 }
6483 else if (!strcmp(args[0], "reqiallow")) { /* allow a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006484 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006485 SMP_OPT_DIR_REQ, ACT_ALLOW, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006486 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006487 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006488 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006489 }
Willy Tarreaub8750a82006-09-03 09:56:00 +02006490 else if (!strcmp(args[0], "reqitarpit")) { /* tarpit a request if a header matches this regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006491 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006492 SMP_OPT_DIR_REQ, ACT_TARPIT, REG_ICASE,
Willy Tarreau5321c422010-01-28 20:35:13 +01006493 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006494 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006495 goto out;
Willy Tarreaub8750a82006-09-03 09:56:00 +02006496 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006497 else if (!strcmp(args[0], "reqadd")) { /* add request header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006498 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006499
Willy Tarreaubaaee002006-06-26 02:48:02 +02006500 if (curproxy == &defproxy) {
6501 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006502 err_code |= ERR_ALERT | ERR_FATAL;
6503 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006504 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006505 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006506 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006507
Willy Tarreaubaaee002006-06-26 02:48:02 +02006508 if (*(args[1]) == 0) {
6509 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006510 err_code |= ERR_ALERT | ERR_FATAL;
6511 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006512 }
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006513
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006514 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006515 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6516 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6517 file, linenum, args[0], errmsg);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006518 err_code |= ERR_ALERT | ERR_FATAL;
6519 goto out;
6520 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006521 err_code |= warnif_cond_conflicts(cond,
6522 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
6523 file, linenum);
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006524 }
6525 else if (*args[2]) {
6526 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6527 file, linenum, args[0], args[2]);
6528 err_code |= ERR_ALERT | ERR_FATAL;
6529 goto out;
6530 }
6531
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006532 wl = calloc(1, sizeof(*wl));
Willy Tarreau8abd4cd2010-01-31 14:30:44 +01006533 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006534 wl->s = strdup(args[1]);
6535 LIST_ADDQ(&curproxy->req_add, &wl->list);
Willy Tarreau61d18892009-03-31 10:49:21 +02006536 warnif_misplaced_reqadd(curproxy, file, linenum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006537 }
6538 else if (!strcmp(args[0], "srvexp") || !strcmp(args[0], "rsprep")) { /* replace response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006539 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006540 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6541 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006542 err_code |= ERR_ALERT | ERR_FATAL;
6543 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006544 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006545
Willy Tarreauade5ec42010-01-28 19:33:49 +01006546 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006547 SMP_OPT_DIR_RES, ACT_REPLACE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006548 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006549 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006550 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006551 }
6552 else if (!strcmp(args[0], "rspdel")) { /* delete response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006553 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006554 SMP_OPT_DIR_RES, ACT_REMOVE, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006555 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006556 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006557 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006558 }
6559 else if (!strcmp(args[0], "rspdeny")) { /* block response header from a regex */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006560 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006561 SMP_OPT_DIR_RES, ACT_DENY, 0,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006562 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006563 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006564 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006565 }
6566 else if (!strcmp(args[0], "rspirep")) { /* replace response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006567 if (*(args[2]) == 0) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02006568 Alert("parsing [%s:%d] : '%s' expects <search> and <replace> as arguments.\n",
6569 file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006570 err_code |= ERR_ALERT | ERR_FATAL;
6571 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006572 }
6573
Willy Tarreauade5ec42010-01-28 19:33:49 +01006574 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006575 SMP_OPT_DIR_RES, ACT_REPLACE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006576 args[0], args[1], args[2], (const char **)args+3);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006577 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006578 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006579 }
6580 else if (!strcmp(args[0], "rspidel")) { /* delete response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006581 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006582 SMP_OPT_DIR_RES, ACT_REMOVE, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006583 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006584 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006585 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006586 }
6587 else if (!strcmp(args[0], "rspideny")) { /* block response header from a regex ignoring case */
Willy Tarreauade5ec42010-01-28 19:33:49 +01006588 err_code |= create_cond_regex_rule(file, linenum, curproxy,
Willy Tarreau32a6f2e2012-04-25 10:13:36 +02006589 SMP_OPT_DIR_RES, ACT_DENY, REG_ICASE,
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006590 args[0], args[1], NULL, (const char **)args+2);
Willy Tarreauade5ec42010-01-28 19:33:49 +01006591 if (err_code & ERR_FATAL)
Willy Tarreau93893792009-07-23 13:19:11 +02006592 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006593 }
6594 else if (!strcmp(args[0], "rspadd")) { /* add response header */
Willy Tarreauf4f04122010-01-28 18:10:50 +01006595 struct cond_wordlist *wl;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006596
Willy Tarreaubaaee002006-06-26 02:48:02 +02006597 if (curproxy == &defproxy) {
6598 Alert("parsing [%s:%d] : '%s' not allowed in 'defaults' section.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006599 err_code |= ERR_ALERT | ERR_FATAL;
6600 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006601 }
Willy Tarreau977b8e42006-12-29 14:19:17 +01006602 else if (warnifnotcap(curproxy, PR_CAP_RS, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006603 err_code |= ERR_WARN;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006604
Willy Tarreaubaaee002006-06-26 02:48:02 +02006605 if (*(args[1]) == 0) {
6606 Alert("parsing [%s:%d] : '%s' expects <header> as an argument.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006607 err_code |= ERR_ALERT | ERR_FATAL;
6608 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006609 }
6610
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006611 if ((strcmp(args[2], "if") == 0 || strcmp(args[2], "unless") == 0)) {
Willy Tarreaub7451bb2012-04-27 12:38:15 +02006612 if ((cond = build_acl_cond(file, linenum, curproxy, (const char **)args+2, &errmsg)) == NULL) {
6613 Alert("parsing [%s:%d] : error detected while parsing a '%s' condition : %s.\n",
6614 file, linenum, args[0], errmsg);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006615 err_code |= ERR_ALERT | ERR_FATAL;
6616 goto out;
6617 }
Willy Tarreaua91d0a52013-03-25 08:12:18 +01006618 err_code |= warnif_cond_conflicts(cond,
6619 (curproxy->cap & PR_CAP_BE) ? SMP_VAL_BE_HRS_HDR : SMP_VAL_FE_HRS_HDR,
6620 file, linenum);
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006621 }
6622 else if (*args[2]) {
6623 Alert("parsing [%s:%d] : '%s' : Expecting nothing, 'if', or 'unless', got '%s'.\n",
6624 file, linenum, args[0], args[2]);
6625 err_code |= ERR_ALERT | ERR_FATAL;
6626 goto out;
6627 }
6628
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006629 wl = calloc(1, sizeof(*wl));
Willy Tarreaufdb563c2010-01-31 15:43:27 +01006630 wl->cond = cond;
Willy Tarreaudeb9ed82010-01-03 21:03:22 +01006631 wl->s = strdup(args[1]);
6632 LIST_ADDQ(&curproxy->rsp_add, &wl->list);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006633 }
6634 else if (!strcmp(args[0], "errorloc") ||
6635 !strcmp(args[0], "errorloc302") ||
6636 !strcmp(args[0], "errorloc303")) { /* error location */
6637 int errnum, errlen;
6638 char *err;
6639
Willy Tarreau977b8e42006-12-29 14:19:17 +01006640 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006641 err_code |= ERR_WARN;
Willy Tarreau977b8e42006-12-29 14:19:17 +01006642
Willy Tarreaubaaee002006-06-26 02:48:02 +02006643 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006644 Alert("parsing [%s:%d] : <%s> expects <status_code> and <url> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006645 err_code |= ERR_ALERT | ERR_FATAL;
6646 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006647 }
6648
6649 errnum = atol(args[1]);
6650 if (!strcmp(args[0], "errorloc303")) {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006651 errlen = strlen(HTTP_303) + strlen(args[2]) + 5;
6652 err = malloc(errlen);
6653 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_303, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006654 } else {
Willy Tarreau348acfe2014-04-14 15:00:39 +02006655 errlen = strlen(HTTP_302) + strlen(args[2]) + 5;
6656 err = malloc(errlen);
6657 errlen = snprintf(err, errlen, "%s%s\r\n\r\n", HTTP_302, args[2]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006658 }
6659
Willy Tarreau0f772532006-12-23 20:51:41 +01006660 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6661 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006662 chunk_destroy(&curproxy->errmsg[rc]);
6663 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau0f772532006-12-23 20:51:41 +01006664 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006665 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006666 }
Willy Tarreau0f772532006-12-23 20:51:41 +01006667
6668 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006669 Warning("parsing [%s:%d] : status code %d not handled by '%s', error relocation will be ignored.\n",
6670 file, linenum, errnum, args[0]);
Willy Tarreaubaaee002006-06-26 02:48:02 +02006671 free(err);
6672 }
6673 }
Willy Tarreau3f49b302007-06-11 00:29:26 +02006674 else if (!strcmp(args[0], "errorfile")) { /* error message from a file */
6675 int errnum, errlen, fd;
6676 char *err;
6677 struct stat stat;
6678
6679 if (warnifnotcap(curproxy, PR_CAP_FE | PR_CAP_BE, file, linenum, args[0], NULL))
Willy Tarreau93893792009-07-23 13:19:11 +02006680 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006681
6682 if (*(args[2]) == 0) {
Willy Tarreau1772ece2009-04-03 14:49:12 +02006683 Alert("parsing [%s:%d] : <%s> expects <status_code> and <file> as arguments.\n", file, linenum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006684 err_code |= ERR_ALERT | ERR_FATAL;
6685 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006686 }
6687
6688 fd = open(args[2], O_RDONLY);
6689 if ((fd < 0) || (fstat(fd, &stat) < 0)) {
6690 Alert("parsing [%s:%d] : error opening file <%s> for custom error message <%s>.\n",
6691 file, linenum, args[2], args[1]);
6692 if (fd >= 0)
6693 close(fd);
Willy Tarreau93893792009-07-23 13:19:11 +02006694 err_code |= ERR_ALERT | ERR_FATAL;
6695 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006696 }
6697
Willy Tarreau27a674e2009-08-17 07:23:33 +02006698 if (stat.st_size <= global.tune.bufsize) {
Willy Tarreau3f49b302007-06-11 00:29:26 +02006699 errlen = stat.st_size;
6700 } else {
6701 Warning("parsing [%s:%d] : custom error message file <%s> larger than %d bytes. Truncating.\n",
Willy Tarreau27a674e2009-08-17 07:23:33 +02006702 file, linenum, args[2], global.tune.bufsize);
Willy Tarreau93893792009-07-23 13:19:11 +02006703 err_code |= ERR_WARN;
Willy Tarreau27a674e2009-08-17 07:23:33 +02006704 errlen = global.tune.bufsize;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006705 }
6706
6707 err = malloc(errlen); /* malloc() must succeed during parsing */
6708 errnum = read(fd, err, errlen);
6709 if (errnum != errlen) {
6710 Alert("parsing [%s:%d] : error reading file <%s> for custom error message <%s>.\n",
6711 file, linenum, args[2], args[1]);
6712 close(fd);
6713 free(err);
Willy Tarreau93893792009-07-23 13:19:11 +02006714 err_code |= ERR_ALERT | ERR_FATAL;
6715 goto out;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006716 }
6717 close(fd);
6718
6719 errnum = atol(args[1]);
6720 for (rc = 0; rc < HTTP_ERR_SIZE; rc++) {
6721 if (http_err_codes[rc] == errnum) {
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +02006722 chunk_destroy(&curproxy->errmsg[rc]);
6723 chunk_initlen(&curproxy->errmsg[rc], err, errlen, errlen);
Willy Tarreau3f49b302007-06-11 00:29:26 +02006724 break;
6725 }
6726 }
6727
6728 if (rc >= HTTP_ERR_SIZE) {
Willy Tarreaubb3c09a2015-09-27 15:13:30 +02006729 Warning("parsing [%s:%d] : status code %d not handled by '%s', error customization will be ignored.\n",
6730 file, linenum, errnum, args[0]);
Willy Tarreau93893792009-07-23 13:19:11 +02006731 err_code |= ERR_WARN;
Willy Tarreau3f49b302007-06-11 00:29:26 +02006732 free(err);
6733 }
6734 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02006735 else {
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006736 struct cfg_kw_list *kwl;
6737 int index;
6738
6739 list_for_each_entry(kwl, &cfg_keywords.list, list) {
6740 for (index = 0; kwl->kw[index].kw != NULL; index++) {
6741 if (kwl->kw[index].section != CFG_LISTEN)
6742 continue;
6743 if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
6744 /* prepare error message just in case */
Willy Tarreau28a47d62012-09-18 20:02:48 +02006745 rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, &defproxy, file, linenum, &errmsg);
Willy Tarreau39f23b62008-07-09 20:22:56 +02006746 if (rc < 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006747 Alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006748 err_code |= ERR_ALERT | ERR_FATAL;
6749 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006750 }
Willy Tarreau39f23b62008-07-09 20:22:56 +02006751 else if (rc > 0) {
Willy Tarreau0a3dd742012-05-08 19:47:01 +02006752 Warning("parsing [%s:%d] : %s\n", file, linenum, errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006753 err_code |= ERR_WARN;
6754 goto out;
Willy Tarreau39f23b62008-07-09 20:22:56 +02006755 }
Willy Tarreau93893792009-07-23 13:19:11 +02006756 goto out;
Willy Tarreau5b2c3362008-07-09 19:39:06 +02006757 }
6758 }
6759 }
William Lallemand82fe75c2012-10-23 10:25:10 +02006760
Willy Tarreau6daf3432008-01-22 16:44:08 +01006761 Alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section\n", file, linenum, args[0], cursection);
Willy Tarreau93893792009-07-23 13:19:11 +02006762 err_code |= ERR_ALERT | ERR_FATAL;
6763 goto out;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006764 }
Willy Tarreau93893792009-07-23 13:19:11 +02006765 out:
Willy Tarreauf4068b62012-05-08 17:37:49 +02006766 free(errmsg);
Willy Tarreau93893792009-07-23 13:19:11 +02006767 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02006768}
6769
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006770int
KOVACS Krisztianb3e54fe2014-11-17 15:11:45 +01006771cfg_parse_netns(const char *file, int linenum, char **args, int kwm)
6772{
6773#ifdef CONFIG_HAP_NS
6774 const char *err;
6775 const char *item = args[0];
6776
6777 if (!strcmp(item, "namespace_list")) {
6778 return 0;
6779 }
6780 else if (!strcmp(item, "namespace")) {
6781 size_t idx = 1;
6782 const char *current;
6783 while (*(current = args[idx++])) {
6784 err = invalid_char(current);
6785 if (err) {
6786 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6787 file, linenum, *err, item, current);
6788 return ERR_ALERT | ERR_FATAL;
6789 }
6790
6791 if (netns_store_lookup(current, strlen(current))) {
6792 Alert("parsing [%s:%d]: Namespace '%s' is already added.\n",
6793 file, linenum, current);
6794 return ERR_ALERT | ERR_FATAL;
6795 }
6796 if (!netns_store_insert(current)) {
6797 Alert("parsing [%s:%d]: Cannot open namespace '%s'.\n",
6798 file, linenum, current);
6799 return ERR_ALERT | ERR_FATAL;
6800 }
6801 }
6802 }
6803
6804 return 0;
6805#else
6806 Alert("parsing [%s:%d]: namespace support is not compiled in.",
6807 file, linenum);
6808 return ERR_ALERT | ERR_FATAL;
6809#endif
6810}
6811
6812int
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006813cfg_parse_users(const char *file, int linenum, char **args, int kwm)
6814{
6815
6816 int err_code = 0;
6817 const char *err;
6818
6819 if (!strcmp(args[0], "userlist")) { /* new userlist */
6820 struct userlist *newul;
6821
6822 if (!*args[1]) {
6823 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6824 file, linenum, args[0]);
6825 err_code |= ERR_ALERT | ERR_FATAL;
6826 goto out;
6827 }
William Lallemand6e62fb62015-04-28 16:55:23 +02006828 if (alertif_too_many_args(1, file, linenum, args, &err_code))
6829 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006830
6831 err = invalid_char(args[1]);
6832 if (err) {
6833 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6834 file, linenum, *err, args[0], args[1]);
6835 err_code |= ERR_ALERT | ERR_FATAL;
6836 goto out;
6837 }
6838
6839 for (newul = userlist; newul; newul = newul->next)
6840 if (!strcmp(newul->name, args[1])) {
6841 Warning("parsing [%s:%d]: ignoring duplicated userlist '%s'.\n",
6842 file, linenum, args[1]);
6843 err_code |= ERR_WARN;
6844 goto out;
6845 }
6846
Vincent Bernat02779b62016-04-03 13:48:43 +02006847 newul = calloc(1, sizeof(*newul));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006848 if (!newul) {
6849 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6850 err_code |= ERR_ALERT | ERR_ABORT;
6851 goto out;
6852 }
6853
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006854 newul->name = strdup(args[1]);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006855 if (!newul->name) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006856 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6857 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier97880bb2016-04-08 10:35:26 +01006858 free(newul);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006859 goto out;
6860 }
6861
6862 newul->next = userlist;
6863 userlist = newul;
6864
6865 } else if (!strcmp(args[0], "group")) { /* new group */
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006866 int cur_arg;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006867 const char *err;
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006868 struct auth_groups *ag;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006869
6870 if (!*args[1]) {
6871 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6872 file, linenum, args[0]);
6873 err_code |= ERR_ALERT | ERR_FATAL;
6874 goto out;
6875 }
6876
6877 err = invalid_char(args[1]);
6878 if (err) {
6879 Alert("parsing [%s:%d]: character '%c' is not permitted in '%s' name '%s'.\n",
6880 file, linenum, *err, args[0], args[1]);
6881 err_code |= ERR_ALERT | ERR_FATAL;
6882 goto out;
6883 }
6884
William Lallemand4ac9f542015-05-28 18:03:51 +02006885 if (!userlist)
6886 goto out;
6887
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006888 for (ag = userlist->groups; ag; ag = ag->next)
6889 if (!strcmp(ag->name, args[1])) {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006890 Warning("parsing [%s:%d]: ignoring duplicated group '%s' in userlist '%s'.\n",
6891 file, linenum, args[1], userlist->name);
6892 err_code |= ERR_ALERT;
6893 goto out;
6894 }
6895
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006896 ag = calloc(1, sizeof(*ag));
6897 if (!ag) {
6898 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6899 err_code |= ERR_ALERT | ERR_ABORT;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006900 goto out;
6901 }
6902
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006903 ag->name = strdup(args[1]);
David Carlier70d60452016-08-22 23:27:42 +01006904 if (!ag->name) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006905 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6906 err_code |= ERR_ALERT | ERR_ABORT;
David Carlier70d60452016-08-22 23:27:42 +01006907 free(ag);
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006908 goto out;
6909 }
6910
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006911 cur_arg = 2;
6912
6913 while (*args[cur_arg]) {
6914 if (!strcmp(args[cur_arg], "users")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006915 ag->groupusers = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006916 cur_arg += 2;
6917 continue;
6918 } else {
6919 Alert("parsing [%s:%d]: '%s' only supports 'users' option.\n",
6920 file, linenum, args[0]);
6921 err_code |= ERR_ALERT | ERR_FATAL;
David Carlier70d60452016-08-22 23:27:42 +01006922 free(ag->groupusers);
6923 free(ag->name);
6924 free(ag);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006925 goto out;
6926 }
6927 }
6928
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006929 ag->next = userlist->groups;
6930 userlist->groups = ag;
6931
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006932 } else if (!strcmp(args[0], "user")) { /* new user */
6933 struct auth_users *newuser;
6934 int cur_arg;
6935
6936 if (!*args[1]) {
6937 Alert("parsing [%s:%d]: '%s' expects <name> as arguments.\n",
6938 file, linenum, args[0]);
6939 err_code |= ERR_ALERT | ERR_FATAL;
6940 goto out;
6941 }
William Lallemand4ac9f542015-05-28 18:03:51 +02006942 if (!userlist)
6943 goto out;
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006944
6945 for (newuser = userlist->users; newuser; newuser = newuser->next)
6946 if (!strcmp(newuser->user, args[1])) {
6947 Warning("parsing [%s:%d]: ignoring duplicated user '%s' in userlist '%s'.\n",
6948 file, linenum, args[1], userlist->name);
6949 err_code |= ERR_ALERT;
6950 goto out;
6951 }
6952
Vincent Bernat02779b62016-04-03 13:48:43 +02006953 newuser = calloc(1, sizeof(*newuser));
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006954 if (!newuser) {
6955 Alert("parsing [%s:%d]: out of memory.\n", file, linenum);
6956 err_code |= ERR_ALERT | ERR_ABORT;
6957 goto out;
6958 }
6959
6960 newuser->user = strdup(args[1]);
6961
6962 newuser->next = userlist->users;
6963 userlist->users = newuser;
6964
6965 cur_arg = 2;
6966
6967 while (*args[cur_arg]) {
6968 if (!strcmp(args[cur_arg], "password")) {
Cyril Bonté1a0191d2014-08-29 20:20:02 +02006969#ifdef CONFIG_HAP_CRYPT
6970 if (!crypt("", args[cur_arg + 1])) {
6971 Alert("parsing [%s:%d]: the encrypted password used for user '%s' is not supported by crypt(3).\n",
6972 file, linenum, newuser->user);
6973 err_code |= ERR_ALERT | ERR_FATAL;
6974 goto out;
6975 }
6976#else
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006977 Warning("parsing [%s:%d]: no crypt(3) support compiled, encrypted passwords will not work.\n",
6978 file, linenum);
6979 err_code |= ERR_ALERT;
6980#endif
6981 newuser->pass = strdup(args[cur_arg + 1]);
6982 cur_arg += 2;
6983 continue;
6984 } else if (!strcmp(args[cur_arg], "insecure-password")) {
6985 newuser->pass = strdup(args[cur_arg + 1]);
6986 newuser->flags |= AU_O_INSECURE;
6987 cur_arg += 2;
6988 continue;
6989 } else if (!strcmp(args[cur_arg], "groups")) {
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01006990 newuser->u.groups_names = strdup(args[cur_arg + 1]);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01006991 cur_arg += 2;
6992 continue;
6993 } else {
6994 Alert("parsing [%s:%d]: '%s' only supports 'password', 'insecure-password' and 'groups' options.\n",
6995 file, linenum, args[0]);
6996 err_code |= ERR_ALERT | ERR_FATAL;
6997 goto out;
6998 }
6999 }
7000 } else {
7001 Alert("parsing [%s:%d]: unknown keyword '%s' in '%s' section\n", file, linenum, args[0], "users");
7002 err_code |= ERR_ALERT | ERR_FATAL;
7003 }
7004
7005out:
7006 return err_code;
7007}
Willy Tarreaubaaee002006-06-26 02:48:02 +02007008
7009/*
7010 * This function reads and parses the configuration file given in the argument.
Willy Tarreau058e9072009-07-20 09:30:05 +02007011 * Returns the error code, 0 if OK, or any combination of :
7012 * - ERR_ABORT: must abort ASAP
7013 * - ERR_FATAL: we can continue parsing but not start the service
7014 * - ERR_WARN: a warning has been emitted
7015 * - ERR_ALERT: an alert has been emitted
7016 * Only the two first ones can stop processing, the two others are just
7017 * indicators.
Willy Tarreaubaaee002006-06-26 02:48:02 +02007018 */
Willy Tarreaub17916e2006-10-15 15:17:57 +02007019int readcfgfile(const char *file)
Willy Tarreaubaaee002006-06-26 02:48:02 +02007020{
William Lallemand64e84512015-05-12 14:25:37 +02007021 char *thisline;
7022 int linesize = LINESIZE;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007023 FILE *f;
7024 int linenum = 0;
Willy Tarreau058e9072009-07-20 09:30:05 +02007025 int err_code = 0;
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007026 struct cfg_section *cs = NULL;
7027 struct cfg_section *ics;
William Lallemand64e84512015-05-12 14:25:37 +02007028 int readbytes = 0;
7029
7030 if ((thisline = malloc(sizeof(*thisline) * linesize)) == NULL) {
William Lallemandb2f07452015-05-12 14:27:13 +02007031 Alert("parsing [%s] : out of memory.\n", file);
William Lallemand64e84512015-05-12 14:25:37 +02007032 return -1;
7033 }
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007034
David Carlier97880bb2016-04-08 10:35:26 +01007035 if ((f=fopen(file,"r")) == NULL) {
7036 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007037 return -1;
David Carlier97880bb2016-04-08 10:35:26 +01007038 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007039
William Lallemandb2f07452015-05-12 14:27:13 +02007040next_line:
William Lallemand64e84512015-05-12 14:25:37 +02007041 while (fgets(thisline + readbytes, linesize - readbytes, f) != NULL) {
Willy Tarreau3842f002009-06-14 11:39:52 +02007042 int arg, kwm = KWM_STD;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007043 char *end;
7044 char *args[MAX_LINE_ARGS + 1];
7045 char *line = thisline;
William Lallemandf9873ba2015-05-05 17:37:14 +02007046 int dquote = 0; /* double quote */
7047 int squote = 0; /* simple quote */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007048
Willy Tarreaubaaee002006-06-26 02:48:02 +02007049 linenum++;
7050
7051 end = line + strlen(line);
7052
William Lallemand64e84512015-05-12 14:25:37 +02007053 if (end-line == linesize-1 && *(end-1) != '\n') {
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007054 /* Check if we reached the limit and the last char is not \n.
7055 * Watch out for the last line without the terminating '\n'!
7056 */
William Lallemand64e84512015-05-12 14:25:37 +02007057 char *newline;
7058 int newlinesize = linesize * 2;
7059
7060 newline = realloc(thisline, sizeof(*thisline) * newlinesize);
7061 if (newline == NULL) {
7062 Alert("parsing [%s:%d]: line too long, cannot allocate memory.\n",
7063 file, linenum);
7064 err_code |= ERR_ALERT | ERR_FATAL;
7065 continue;
7066 }
7067
7068 readbytes = linesize - 1;
7069 linesize = newlinesize;
7070 thisline = newline;
7071 continue;
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007072 }
7073
William Lallemand64e84512015-05-12 14:25:37 +02007074 readbytes = 0;
7075
Willy Tarreaubaaee002006-06-26 02:48:02 +02007076 /* skip leading spaces */
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007077 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007078 line++;
William Lallemandf9873ba2015-05-05 17:37:14 +02007079
Willy Tarreaubaaee002006-06-26 02:48:02 +02007080 arg = 0;
7081 args[arg] = line;
7082
7083 while (*line && arg < MAX_LINE_ARGS) {
William Lallemandf9873ba2015-05-05 17:37:14 +02007084 if (*line == '"' && !squote) { /* double quote outside single quotes */
7085 if (dquote)
7086 dquote = 0;
7087 else
7088 dquote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007089 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007090 end--;
7091 }
7092 else if (*line == '\'' && !dquote) { /* single quote outside double quotes */
7093 if (squote)
7094 squote = 0;
7095 else
7096 squote = 1;
William Lallemand3f415602015-05-12 14:01:09 +02007097 memmove(line, line + 1, end - line);
William Lallemandf9873ba2015-05-05 17:37:14 +02007098 end--;
7099 }
7100 else if (*line == '\\' && !squote) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007101 /* first, we'll replace \\, \<space>, \#, \r, \n, \t, \xXX with their
7102 * C equivalent value. Other combinations left unchanged (eg: \1).
7103 */
Willy Tarreaubaaee002006-06-26 02:48:02 +02007104 int skip = 0;
7105 if (line[1] == ' ' || line[1] == '\\' || line[1] == '#') {
7106 *line = line[1];
7107 skip = 1;
7108 }
7109 else if (line[1] == 'r') {
7110 *line = '\r';
7111 skip = 1;
William Lallemandf9873ba2015-05-05 17:37:14 +02007112 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007113 else if (line[1] == 'n') {
7114 *line = '\n';
7115 skip = 1;
7116 }
7117 else if (line[1] == 't') {
7118 *line = '\t';
7119 skip = 1;
7120 }
7121 else if (line[1] == 'x') {
Emeric Brunb982a3d2010-01-04 15:45:53 +01007122 if ((line + 3 < end) && ishex(line[2]) && ishex(line[3])) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007123 unsigned char hex1, hex2;
7124 hex1 = toupper(line[2]) - '0';
7125 hex2 = toupper(line[3]) - '0';
7126 if (hex1 > 9) hex1 -= 'A' - '9' - 1;
7127 if (hex2 > 9) hex2 -= 'A' - '9' - 1;
7128 *line = (hex1<<4) + hex2;
7129 skip = 3;
7130 }
7131 else {
7132 Alert("parsing [%s:%d] : invalid or incomplete '\\x' sequence in '%s'.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007133 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007134 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007135 } else if (line[1] == '"') {
7136 *line = '"';
7137 skip = 1;
7138 } else if (line[1] == '\'') {
7139 *line = '\'';
7140 skip = 1;
William Lallemandb2f07452015-05-12 14:27:13 +02007141 } else if (line[1] == '$' && dquote) { /* escaping of $ only inside double quotes */
7142 *line = '$';
7143 skip = 1;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007144 }
7145 if (skip) {
Cyril Bontédd1b01d2009-12-06 13:43:42 +01007146 memmove(line + 1, line + 1 + skip, end - (line + skip));
Willy Tarreaubaaee002006-06-26 02:48:02 +02007147 end -= skip;
7148 }
7149 line++;
7150 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007151 else if ((!squote && !dquote && *line == '#') || *line == '\n' || *line == '\r') {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007152 /* end of string, end of loop */
7153 *line = 0;
7154 break;
7155 }
William Lallemandf9873ba2015-05-05 17:37:14 +02007156 else if (!squote && !dquote && isspace((unsigned char)*line)) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007157 /* a non-escaped space is an argument separator */
Krzysztof Piotr Oledzkie6bbd742007-11-01 00:33:12 +01007158 *line++ = '\0';
Willy Tarreau8f8e6452007-06-17 21:51:38 +02007159 while (isspace((unsigned char)*line))
Willy Tarreaubaaee002006-06-26 02:48:02 +02007160 line++;
7161 args[++arg] = line;
7162 }
William Lallemandb2f07452015-05-12 14:27:13 +02007163 else if (dquote && *line == '$') {
7164 /* environment variables are evaluated inside double quotes */
7165 char *var_beg;
7166 char *var_end;
7167 char save_char;
7168 char *value;
7169 int val_len;
7170 int newlinesize;
7171 int braces = 0;
7172
7173 var_beg = line + 1;
7174 var_end = var_beg;
7175
7176 if (*var_beg == '{') {
7177 var_beg++;
7178 var_end++;
7179 braces = 1;
7180 }
7181
7182 if (!isalpha((int)(unsigned char)*var_beg) && *var_beg != '_') {
7183 Alert("parsing [%s:%d] : Variable expansion: Unrecognized character '%c' in variable name.\n", file, linenum, *var_beg);
7184 err_code |= ERR_ALERT | ERR_FATAL;
7185 goto next_line; /* skip current line */
7186 }
7187
7188 while (isalnum((int)(unsigned char)*var_end) || *var_end == '_')
7189 var_end++;
7190
7191 save_char = *var_end;
7192 *var_end = '\0';
7193 value = getenv(var_beg);
7194 *var_end = save_char;
7195 val_len = value ? strlen(value) : 0;
7196
7197 if (braces) {
7198 if (*var_end == '}') {
7199 var_end++;
7200 braces = 0;
7201 } else {
7202 Alert("parsing [%s:%d] : Variable expansion: Mismatched braces.\n", file, linenum);
7203 err_code |= ERR_ALERT | ERR_FATAL;
7204 goto next_line; /* skip current line */
7205 }
7206 }
7207
7208 newlinesize = (end - thisline) - (var_end - line) + val_len + 1;
7209
7210 /* if not enough space in thisline */
7211 if (newlinesize > linesize) {
7212 char *newline;
7213
7214 newline = realloc(thisline, newlinesize * sizeof(*thisline));
7215 if (newline == NULL) {
7216 Alert("parsing [%s:%d] : Variable expansion: Not enough memory.\n", file, linenum);
7217 err_code |= ERR_ALERT | ERR_FATAL;
7218 goto next_line; /* slip current line */
7219 }
7220 /* recompute pointers if realloc returns a new pointer */
7221 if (newline != thisline) {
7222 int i;
7223 int diff;
7224
7225 for (i = 0; i <= arg; i++) {
7226 diff = args[i] - thisline;
7227 args[i] = newline + diff;
7228 }
7229
7230 diff = var_end - thisline;
7231 var_end = newline + diff;
7232 diff = end - thisline;
7233 end = newline + diff;
7234 diff = line - thisline;
7235 line = newline + diff;
7236 thisline = newline;
7237 }
7238 linesize = newlinesize;
7239 }
7240
7241 /* insert value inside the line */
7242 memmove(line + val_len, var_end, end - var_end + 1);
7243 memcpy(line, value, val_len);
7244 end += val_len - (var_end - line);
7245 line += val_len;
7246 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007247 else {
7248 line++;
7249 }
7250 }
William Lallemandb2f07452015-05-12 14:27:13 +02007251
William Lallemandf9873ba2015-05-05 17:37:14 +02007252 if (dquote) {
7253 Alert("parsing [%s:%d] : Mismatched double quotes.\n", file, linenum);
7254 err_code |= ERR_ALERT | ERR_FATAL;
7255 }
7256
7257 if (squote) {
7258 Alert("parsing [%s:%d] : Mismatched simple quotes.\n", file, linenum);
7259 err_code |= ERR_ALERT | ERR_FATAL;
7260 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007261
7262 /* empty line */
7263 if (!**args)
7264 continue;
7265
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007266 if (*line) {
7267 /* we had to stop due to too many args.
7268 * Let's terminate the string, print the offending part then cut the
7269 * last arg.
7270 */
7271 while (*line && *line != '#' && *line != '\n' && *line != '\r')
7272 line++;
7273 *line = '\0';
7274
Krzysztof Piotr Oledzki500b8f02009-12-15 22:34:51 +01007275 Alert("parsing [%s:%d]: line too long, truncating at word %d, position %ld: <%s>.\n",
Willy Tarreau3ccf94e2009-12-17 21:12:16 +01007276 file, linenum, arg + 1, (long)(args[arg] - thisline + 1), args[arg]);
Willy Tarreau7bb651e2009-11-09 21:16:53 +01007277 err_code |= ERR_ALERT | ERR_FATAL;
7278 args[arg] = line;
7279 }
7280
Willy Tarreau540abe42007-05-02 20:50:16 +02007281 /* zero out remaining args and ensure that at least one entry
7282 * is zeroed out.
7283 */
7284 while (++arg <= MAX_LINE_ARGS) {
Willy Tarreaubaaee002006-06-26 02:48:02 +02007285 args[arg] = line;
7286 }
7287
Willy Tarreau3842f002009-06-14 11:39:52 +02007288 /* check for keyword modifiers "no" and "default" */
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007289 if (!strcmp(args[0], "no")) {
William Lallemand0f99e342011-10-12 17:50:54 +02007290 char *tmp;
7291
Willy Tarreau3842f002009-06-14 11:39:52 +02007292 kwm = KWM_NO;
William Lallemand0f99e342011-10-12 17:50:54 +02007293 tmp = args[0];
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007294 for (arg=0; *args[arg+1]; arg++)
7295 args[arg] = args[arg+1]; // shift args after inversion
William Lallemand0f99e342011-10-12 17:50:54 +02007296 *tmp = '\0'; // fix the next arg to \0
7297 args[arg] = tmp;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007298 }
Willy Tarreau3842f002009-06-14 11:39:52 +02007299 else if (!strcmp(args[0], "default")) {
7300 kwm = KWM_DEF;
7301 for (arg=0; *args[arg+1]; arg++)
7302 args[arg] = args[arg+1]; // shift args after inversion
7303 }
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007304
William Lallemand0f99e342011-10-12 17:50:54 +02007305 if (kwm != KWM_STD && strcmp(args[0], "option") != 0 && \
7306 strcmp(args[0], "log") != 0) {
7307 Alert("parsing [%s:%d]: negation/default currently supported only for options and log.\n", file, linenum);
Willy Tarreau058e9072009-07-20 09:30:05 +02007308 err_code |= ERR_ALERT | ERR_FATAL;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01007309 }
7310
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007311 /* detect section start */
7312 list_for_each_entry(ics, &sections, list) {
7313 if (strcmp(args[0], ics->section_name) == 0) {
7314 cursection = ics->section_name;
7315 cs = ics;
7316 break;
7317 }
Emeric Brun32da3c42010-09-23 18:39:19 +02007318 }
7319
Willy Tarreaubaaee002006-06-26 02:48:02 +02007320 /* else it's a section keyword */
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01007321 if (cs)
7322 err_code |= cs->section_parser(file, linenum, args, kwm);
7323 else {
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01007324 Alert("parsing [%s:%d]: unknown keyword '%s' out of section.\n", file, linenum, args[0]);
Willy Tarreau058e9072009-07-20 09:30:05 +02007325 err_code |= ERR_ALERT | ERR_FATAL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007326 }
Willy Tarreau058e9072009-07-20 09:30:05 +02007327
7328 if (err_code & ERR_ABORT)
7329 break;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007330 }
Willy Tarreau6daf3432008-01-22 16:44:08 +01007331 cursection = NULL;
William Lallemand64e84512015-05-12 14:25:37 +02007332 free(thisline);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007333 fclose(f);
Willy Tarreau058e9072009-07-20 09:30:05 +02007334 return err_code;
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007335}
7336
Willy Tarreau64ab6072014-09-16 12:17:36 +02007337/* This function propagates processes from frontend <from> to backend <to> so
7338 * that it is always guaranteed that a backend pointed to by a frontend is
7339 * bound to all of its processes. After that, if the target is a "listen"
7340 * instance, the function recursively descends the target's own targets along
Willy Tarreau98d04852015-05-26 12:18:29 +02007341 * default_backend and use_backend rules. Since the bits are
Willy Tarreau64ab6072014-09-16 12:17:36 +02007342 * checked first to ensure that <to> is already bound to all processes of
7343 * <from>, there is no risk of looping and we ensure to follow the shortest
7344 * path to the destination.
7345 *
7346 * It is possible to set <to> to NULL for the first call so that the function
7347 * takes care of visiting the initial frontend in <from>.
7348 *
7349 * It is important to note that the function relies on the fact that all names
7350 * have already been resolved.
7351 */
7352void propagate_processes(struct proxy *from, struct proxy *to)
7353{
7354 struct switching_rule *rule;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007355
7356 if (to) {
7357 /* check whether we need to go down */
7358 if (from->bind_proc &&
7359 (from->bind_proc & to->bind_proc) == from->bind_proc)
7360 return;
7361
7362 if (!from->bind_proc && !to->bind_proc)
7363 return;
7364
7365 to->bind_proc = from->bind_proc ?
7366 (to->bind_proc | from->bind_proc) : 0;
7367
7368 /* now propagate down */
7369 from = to;
7370 }
7371
Willy Tarreau8a95d8c2014-12-18 13:56:26 +01007372 if (!(from->cap & PR_CAP_FE))
Willy Tarreau64ab6072014-09-16 12:17:36 +02007373 return;
7374
Willy Tarreauf6b70012014-12-18 14:00:43 +01007375 if (from->state == PR_STSTOPPED)
7376 return;
7377
Willy Tarreau64ab6072014-09-16 12:17:36 +02007378 /* default_backend */
7379 if (from->defbe.be)
7380 propagate_processes(from, from->defbe.be);
7381
7382 /* use_backend */
7383 list_for_each_entry(rule, &from->switching_rules, list) {
Cyril Bonté51639692014-10-02 19:56:25 +02007384 if (rule->dynamic)
7385 continue;
Willy Tarreau64ab6072014-09-16 12:17:36 +02007386 to = rule->be.backend;
7387 propagate_processes(from, to);
7388 }
Willy Tarreau64ab6072014-09-16 12:17:36 +02007389}
7390
Willy Tarreaubb925012009-07-23 13:36:36 +02007391/*
7392 * Returns the error code, 0 if OK, or any combination of :
7393 * - ERR_ABORT: must abort ASAP
7394 * - ERR_FATAL: we can continue parsing but not start the service
7395 * - ERR_WARN: a warning has been emitted
7396 * - ERR_ALERT: an alert has been emitted
7397 * Only the two first ones can stop processing, the two others are just
7398 * indicators.
7399 */
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007400int check_config_validity()
7401{
7402 int cfgerr = 0;
7403 struct proxy *curproxy = NULL;
7404 struct server *newsrv = NULL;
Willy Tarreaubb925012009-07-23 13:36:36 +02007405 int err_code = 0;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007406 unsigned int next_pxid = 1;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007407 struct bind_conf *bind_conf;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007408
Willy Tarreau2a65ff02012-09-13 17:54:29 +02007409 bind_conf = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007410 /*
7411 * Now, check for the integrity of all that we have collected.
7412 */
7413
7414 /* will be needed further to delay some tasks */
Willy Tarreaub0b37bc2008-06-23 14:00:57 +02007415 tv_update_date(0,1);
Willy Tarreaubaaee002006-06-26 02:48:02 +02007416
Willy Tarreau193b8c62012-11-22 00:17:38 +01007417 if (!global.tune.max_http_hdr)
7418 global.tune.max_http_hdr = MAX_HTTP_HDR;
7419
7420 if (!global.tune.cookie_len)
7421 global.tune.cookie_len = CAPTURE_LEN;
7422
7423 pool2_capture = create_pool("capture", global.tune.cookie_len, MEM_F_SHARED);
7424
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01007425 /* Post initialisation of the users and groups lists. */
7426 err_code = userlist_postinit();
7427 if (err_code != ERR_NONE)
7428 goto out;
7429
Willy Tarreau55bc0f82009-03-15 14:51:53 +01007430 /* first, we will invert the proxy list order */
7431 curproxy = NULL;
7432 while (proxy) {
7433 struct proxy *next;
7434
7435 next = proxy->next;
7436 proxy->next = curproxy;
7437 curproxy = proxy;
7438 if (!next)
7439 break;
7440 proxy = next;
7441 }
7442
Willy Tarreau419ead82014-09-16 13:41:21 +02007443 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007444 struct switching_rule *rule;
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007445 struct server_rule *srule;
Emeric Brunb982a3d2010-01-04 15:45:53 +01007446 struct sticking_rule *mrule;
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02007447 struct act_rule *trule;
7448 struct act_rule *hrqrule;
Dragan Dosen1322d092015-09-22 16:05:32 +02007449 struct logsrv *tmplogsrv;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007450 unsigned int next_id;
Willy Tarreau16a21472012-11-19 12:39:59 +01007451 int nbproc;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007452
Willy Tarreau050536d2012-10-04 08:47:34 +02007453 if (curproxy->uuid < 0) {
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007454 /* proxy ID not set, use automatic numbering with first
7455 * spare entry starting with next_pxid.
7456 */
7457 next_pxid = get_next_id(&used_proxy_id, next_pxid);
7458 curproxy->conf.id.key = curproxy->uuid = next_pxid;
7459 eb32_insert(&used_proxy_id, &curproxy->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02007460 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01007461 next_pxid++;
7462
Willy Tarreau55ea7572007-06-17 19:56:27 +02007463
Willy Tarreaubaaee002006-06-26 02:48:02 +02007464 if (curproxy->state == PR_STSTOPPED) {
Willy Tarreauda250db2008-10-12 12:07:48 +02007465 /* ensure we don't keep listeners uselessly bound */
7466 stop_proxy(curproxy);
Willy Tarreau02df7742015-05-01 19:59:56 +02007467 free((void *)curproxy->table.peers.name);
7468 curproxy->table.peers.p = NULL;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007469 continue;
7470 }
7471
Willy Tarreau102df612014-05-07 23:56:38 +02007472 /* Check multi-process mode compatibility for the current proxy */
7473
7474 if (curproxy->bind_proc) {
7475 /* an explicit bind-process was specified, let's check how many
7476 * processes remain.
7477 */
David Carliere6c39412015-07-02 07:00:17 +00007478 nbproc = my_popcountl(curproxy->bind_proc);
Willy Tarreau102df612014-05-07 23:56:38 +02007479
7480 curproxy->bind_proc &= nbits(global.nbproc);
7481 if (!curproxy->bind_proc && nbproc == 1) {
7482 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);
7483 curproxy->bind_proc = 1;
7484 }
7485 else if (!curproxy->bind_proc && nbproc > 1) {
7486 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);
7487 curproxy->bind_proc = 0;
7488 }
7489 }
7490
Willy Tarreau3d209582014-05-09 17:06:11 +02007491 /* check and reduce the bind-proc of each listener */
7492 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
7493 unsigned long mask;
7494
7495 if (!bind_conf->bind_proc)
7496 continue;
7497
7498 mask = nbits(global.nbproc);
7499 if (curproxy->bind_proc)
7500 mask &= curproxy->bind_proc;
7501 /* mask cannot be null here thanks to the previous checks */
7502
David Carliere6c39412015-07-02 07:00:17 +00007503 nbproc = my_popcountl(bind_conf->bind_proc);
Willy Tarreau3d209582014-05-09 17:06:11 +02007504 bind_conf->bind_proc &= mask;
7505
7506 if (!bind_conf->bind_proc && nbproc == 1) {
7507 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",
7508 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7509 bind_conf->bind_proc = mask & ~(mask - 1);
7510 }
7511 else if (!bind_conf->bind_proc && nbproc > 1) {
7512 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",
7513 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
7514 bind_conf->bind_proc = 0;
7515 }
7516 }
7517
Willy Tarreauff01a212009-03-15 13:46:16 +01007518 switch (curproxy->mode) {
7519 case PR_MODE_HEALTH:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007520 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007521 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007522 Alert("config : %s '%s' cannot be in health mode as it has no frontend capability.\n",
7523 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007524 cfgerr++;
7525 }
7526
7527 if (curproxy->srv != NULL)
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007528 Warning("config : servers will be ignored for %s '%s'.\n",
7529 proxy_type_str(curproxy), curproxy->id);
Willy Tarreauff01a212009-03-15 13:46:16 +01007530 break;
7531
7532 case PR_MODE_TCP:
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007533 cfgerr += proxy_cfg_ensure_no_http(curproxy);
Willy Tarreauff01a212009-03-15 13:46:16 +01007534 break;
7535
7536 case PR_MODE_HTTP:
Willy Tarreau25320b22013-03-24 07:22:08 +01007537 curproxy->http_needed = 1;
Willy Tarreauff01a212009-03-15 13:46:16 +01007538 break;
7539 }
7540
Willy Tarreauf3934b82015-08-11 11:36:45 +02007541 if ((curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->conf.listeners)) {
7542 Warning("config : %s '%s' has no 'bind' directive. Please declare it as a backend if this was intended.\n",
7543 proxy_type_str(curproxy), curproxy->id);
7544 err_code |= ERR_WARN;
7545 }
7546
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007547 if ((curproxy->cap & PR_CAP_BE) && (curproxy->mode != PR_MODE_HEALTH)) {
Willy Tarreauf3e49f92009-10-03 12:21:20 +02007548 if (curproxy->lbprm.algo & BE_LB_KIND) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007549 if (curproxy->options & PR_O_TRANSP) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007550 Alert("config : %s '%s' cannot use both transparent and balance mode.\n",
7551 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007552 cfgerr++;
7553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007554#ifdef WE_DONT_SUPPORT_SERVERLESS_LISTENERS
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007555 else if (curproxy->srv == NULL) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007556 Alert("config : %s '%s' needs at least 1 server in balance mode.\n",
7557 proxy_type_str(curproxy), curproxy->id);
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007558 cfgerr++;
7559 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007560#endif
Willy Tarreau1620ec32011-08-06 17:05:02 +02007561 else if (curproxy->options & PR_O_DISPATCH) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02007562 Warning("config : dispatch address of %s '%s' will be ignored in balance mode.\n",
7563 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02007564 err_code |= ERR_WARN;
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007565 }
7566 }
Willy Tarreau1620ec32011-08-06 17:05:02 +02007567 else if (!(curproxy->options & (PR_O_TRANSP | PR_O_DISPATCH | PR_O_HTTP_PROXY))) {
Willy Tarreau3cd9af22009-03-15 14:06:41 +01007568 /* If no LB algo is set in a backend, and we're not in
7569 * transparent mode, dispatch mode nor proxy mode, we
7570 * want to use balance roundrobin by default.
7571 */
7572 curproxy->lbprm.algo &= ~BE_LB_ALGO;
7573 curproxy->lbprm.algo |= BE_LB_ALGO_RR;
Willy Tarreaubaaee002006-06-26 02:48:02 +02007574 }
7575 }
Willy Tarreau193cf932007-09-17 10:17:23 +02007576
Willy Tarreau1620ec32011-08-06 17:05:02 +02007577 if (curproxy->options & PR_O_DISPATCH)
7578 curproxy->options &= ~(PR_O_TRANSP | PR_O_HTTP_PROXY);
7579 else if (curproxy->options & PR_O_HTTP_PROXY)
7580 curproxy->options &= ~(PR_O_DISPATCH | PR_O_TRANSP);
7581 else if (curproxy->options & PR_O_TRANSP)
7582 curproxy->options &= ~(PR_O_DISPATCH | PR_O_HTTP_PROXY);
Willy Tarreau82936582007-11-30 15:20:09 +01007583
Willy Tarreau1620ec32011-08-06 17:05:02 +02007584 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_HTTP_CHK) {
7585 if (curproxy->options & PR_O_DISABLE404) {
7586 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7587 "disable-on-404", proxy_type_str(curproxy), curproxy->id);
7588 err_code |= ERR_WARN;
7589 curproxy->options &= ~PR_O_DISABLE404;
7590 }
7591 if (curproxy->options2 & PR_O2_CHK_SNDST) {
7592 Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
7593 "send-state", proxy_type_str(curproxy), curproxy->id);
7594 err_code |= ERR_WARN;
7595 curproxy->options &= ~PR_O2_CHK_SNDST;
7596 }
Willy Tarreauef781042010-01-27 11:53:01 +01007597 }
7598
Simon Horman98637e52014-06-20 12:30:16 +09007599 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_EXT_CHK) {
7600 if (!global.external_check) {
7601 Alert("Proxy '%s' : '%s' unable to find required 'global.external-check'.\n",
7602 curproxy->id, "option external-check");
7603 cfgerr++;
7604 }
7605 if (!curproxy->check_command) {
7606 Alert("Proxy '%s' : '%s' unable to find required 'external-check command'.\n",
7607 curproxy->id, "option external-check");
7608 cfgerr++;
7609 }
7610 }
7611
Simon Horman64e34162015-02-06 11:11:57 +09007612 if (curproxy->email_alert.set) {
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007613 if (!(curproxy->email_alert.mailers.name && curproxy->email_alert.from && curproxy->email_alert.to)) {
7614 Warning("config : 'email-alert' will be ignored for %s '%s' (the presence any of "
Pieter Baauw8669e972015-08-17 00:45:05 +02007615 "'email-alert from', 'email-alert level' 'email-alert mailers', "
7616 "'email-alert myhostname', or 'email-alert to' "
7617 "requires each of 'email-alert from', 'email-alert mailers' and 'email-alert to' "
Simon Horman0ba0e4a2015-01-30 11:23:00 +09007618 "to be present).\n",
7619 proxy_type_str(curproxy), curproxy->id);
7620 err_code |= ERR_WARN;
7621 free_email_alert(curproxy);
7622 }
7623 if (!curproxy->email_alert.myhostname)
Cyril Bontée22bfd62015-12-04 03:07:07 +01007624 curproxy->email_alert.myhostname = strdup(hostname);
Simon Horman9dc49962015-01-30 11:22:59 +09007625 }
7626
Simon Horman98637e52014-06-20 12:30:16 +09007627 if (curproxy->check_command) {
7628 int clear = 0;
7629 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7630 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7631 "external-check command", proxy_type_str(curproxy), curproxy->id);
7632 err_code |= ERR_WARN;
7633 clear = 1;
7634 }
7635 if (curproxy->check_command[0] != '/' && !curproxy->check_path) {
Ben Cabot49795eb2015-09-16 12:07:51 +01007636 Alert("Proxy '%s': '%s' does not have a leading '/' and 'external-check path' is not set.\n",
Simon Horman98637e52014-06-20 12:30:16 +09007637 curproxy->id, "external-check command");
7638 cfgerr++;
7639 }
7640 if (clear) {
7641 free(curproxy->check_command);
7642 curproxy->check_command = NULL;
7643 }
7644 }
7645
7646 if (curproxy->check_path) {
7647 if ((curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_EXT_CHK) {
7648 Warning("config : '%s' will be ignored for %s '%s' (requires 'option external-check').\n",
7649 "external-check path", proxy_type_str(curproxy), curproxy->id);
7650 err_code |= ERR_WARN;
7651 free(curproxy->check_path);
7652 curproxy->check_path = NULL;
7653 }
7654 }
7655
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007656 /* if a default backend was specified, let's find it */
7657 if (curproxy->defbe.name) {
7658 struct proxy *target;
7659
Willy Tarreauafb39922015-05-26 12:04:09 +02007660 target = proxy_be_by_name(curproxy->defbe.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007661 if (!target) {
7662 Alert("Proxy '%s': unable to find required default_backend: '%s'.\n",
7663 curproxy->id, curproxy->defbe.name);
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007664 cfgerr++;
7665 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007666 Alert("Proxy '%s': loop detected for default_backend: '%s'.\n",
7667 curproxy->id, curproxy->defbe.name);
Willy Tarreaubb925012009-07-23 13:36:36 +02007668 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007669 } else if (target->mode != curproxy->mode &&
7670 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7671
7672 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) as its default backend (see 'mode').\n",
7673 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7674 curproxy->conf.file, curproxy->conf.line,
7675 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7676 target->conf.file, target->conf.line);
7677 cfgerr++;
Willy Tarreau5fdfb912007-01-01 23:11:07 +01007678 } else {
7679 free(curproxy->defbe.name);
7680 curproxy->defbe.be = target;
Willy Tarreauff678132012-02-13 14:32:34 +01007681
7682 /* Emit a warning if this proxy also has some servers */
7683 if (curproxy->srv) {
7684 Warning("In proxy '%s', the 'default_backend' rule always has precedence over the servers, which will never be used.\n",
7685 curproxy->id);
7686 err_code |= ERR_WARN;
7687 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02007688 }
7689 }
7690
Willy Tarreau55ea7572007-06-17 19:56:27 +02007691 /* find the target proxy for 'use_backend' rules */
7692 list_for_each_entry(rule, &curproxy->switching_rules, list) {
Willy Tarreau55ea7572007-06-17 19:56:27 +02007693 struct proxy *target;
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01007694 struct logformat_node *node;
7695 char *pxname;
7696
7697 /* Try to parse the string as a log format expression. If the result
7698 * of the parsing is only one entry containing a simple string, then
7699 * it's a standard string corresponding to a static rule, thus the
7700 * parsing is cancelled and be.name is restored to be resolved.
7701 */
7702 pxname = rule->be.name;
7703 LIST_INIT(&rule->be.expr);
7704 parse_logformat_string(pxname, curproxy, &rule->be.expr, 0, SMP_VAL_FE_HRQ_HDR,
7705 curproxy->conf.args.file, curproxy->conf.args.line);
7706 node = LIST_NEXT(&rule->be.expr, struct logformat_node *, list);
7707
7708 if (!LIST_ISEMPTY(&rule->be.expr)) {
7709 if (node->type != LOG_FMT_TEXT || node->list.n != &rule->be.expr) {
7710 rule->dynamic = 1;
7711 free(pxname);
7712 continue;
7713 }
7714 /* simple string: free the expression and fall back to static rule */
7715 free(node->arg);
7716 free(node);
7717 }
7718
7719 rule->dynamic = 0;
7720 rule->be.name = pxname;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007721
Willy Tarreauafb39922015-05-26 12:04:09 +02007722 target = proxy_be_by_name(rule->be.name);
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007723 if (!target) {
7724 Alert("Proxy '%s': unable to find required use_backend: '%s'.\n",
7725 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007726 cfgerr++;
7727 } else if (target == curproxy) {
Krzysztof Piotr Oledzki6eb730d2007-11-03 23:41:58 +01007728 Alert("Proxy '%s': loop detected for use_backend: '%s'.\n",
7729 curproxy->id, rule->be.name);
Willy Tarreau55ea7572007-06-17 19:56:27 +02007730 cfgerr++;
Willy Tarreauafb39922015-05-26 12:04:09 +02007731 } else if (target->mode != curproxy->mode &&
7732 !(curproxy->mode == PR_MODE_TCP && target->mode == PR_MODE_HTTP)) {
7733
7734 Alert("%s %s '%s' (%s:%d) tries to use incompatible %s %s '%s' (%s:%d) in a 'use_backend' rule (see 'mode').\n",
7735 proxy_mode_str(curproxy->mode), proxy_type_str(curproxy), curproxy->id,
7736 curproxy->conf.file, curproxy->conf.line,
7737 proxy_mode_str(target->mode), proxy_type_str(target), target->id,
7738 target->conf.file, target->conf.line);
7739 cfgerr++;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007740 } else {
7741 free((void *)rule->be.name);
7742 rule->be.backend = target;
7743 }
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007744 }
7745
Willy Tarreau64ab6072014-09-16 12:17:36 +02007746 /* find the target server for 'use_server' rules */
Willy Tarreau4a5cade2012-04-05 21:09:48 +02007747 list_for_each_entry(srule, &curproxy->server_rules, list) {
7748 struct server *target = findserver(curproxy, srule->srv.name);
7749
7750 if (!target) {
7751 Alert("config : %s '%s' : unable to find server '%s' referenced in a 'use-server' rule.\n",
7752 proxy_type_str(curproxy), curproxy->id, srule->srv.name);
7753 cfgerr++;
7754 continue;
7755 }
7756 free((void *)srule->srv.name);
7757 srule->srv.ptr = target;
Willy Tarreau55ea7572007-06-17 19:56:27 +02007758 }
7759
Emeric Brunb982a3d2010-01-04 15:45:53 +01007760 /* find the target table for 'stick' rules */
7761 list_for_each_entry(mrule, &curproxy->sticking_rules, list) {
7762 struct proxy *target;
7763
Emeric Brun1d33b292010-01-04 15:47:17 +01007764 curproxy->be_req_ana |= AN_REQ_STICKING_RULES;
7765 if (mrule->flags & STK_IS_STORE)
7766 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7767
Emeric Brunb982a3d2010-01-04 15:45:53 +01007768 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007769 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007770 else
7771 target = curproxy;
7772
7773 if (!target) {
7774 Alert("Proxy '%s': unable to find stick-table '%s'.\n",
7775 curproxy->id, mrule->table.name);
7776 cfgerr++;
7777 }
7778 else if (target->table.size == 0) {
7779 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7780 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7781 cfgerr++;
7782 }
Willy Tarreau12785782012-04-27 21:37:17 +02007783 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7784 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007785 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7786 cfgerr++;
7787 }
7788 else {
7789 free((void *)mrule->table.name);
7790 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007791 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007792 }
7793 }
7794
7795 /* find the target table for 'store response' rules */
7796 list_for_each_entry(mrule, &curproxy->storersp_rules, list) {
7797 struct proxy *target;
7798
Emeric Brun1d33b292010-01-04 15:47:17 +01007799 curproxy->be_rsp_ana |= AN_RES_STORE_RULES;
7800
Emeric Brunb982a3d2010-01-04 15:45:53 +01007801 if (mrule->table.name)
Willy Tarreau9e0bb102015-05-26 11:24:42 +02007802 target = proxy_tbl_by_name(mrule->table.name);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007803 else
7804 target = curproxy;
7805
7806 if (!target) {
7807 Alert("Proxy '%s': unable to find store table '%s'.\n",
7808 curproxy->id, mrule->table.name);
7809 cfgerr++;
7810 }
7811 else if (target->table.size == 0) {
7812 Alert("Proxy '%s': stick-table '%s' used but not configured.\n",
7813 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7814 cfgerr++;
7815 }
Willy Tarreau12785782012-04-27 21:37:17 +02007816 else if (!stktable_compatible_sample(mrule->expr, target->table.type)) {
7817 Alert("Proxy '%s': type of fetch not usable with type of stick-table '%s'.\n",
Emeric Brunb982a3d2010-01-04 15:45:53 +01007818 curproxy->id, mrule->table.name ? mrule->table.name : curproxy->id);
7819 cfgerr++;
7820 }
7821 else {
7822 free((void *)mrule->table.name);
7823 mrule->table.t = &(target->table);
Willy Tarreau888617d2010-06-20 09:11:39 +02007824 stktable_alloc_data_type(&target->table, STKTABLE_DT_SERVER_ID, NULL);
Emeric Brunb982a3d2010-01-04 15:45:53 +01007825 }
7826 }
7827
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007828 /* find the target table for 'tcp-request' layer 4 rules */
7829 list_for_each_entry(trule, &curproxy->tcp_req.l4_rules, list) {
7830 struct proxy *target;
7831
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007832 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007833 continue;
7834
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007835 if (trule->arg.trk_ctr.table.n)
7836 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007837 else
7838 target = curproxy;
7839
7840 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007841 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007842 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007843 tcp_trk_idx(trule->action));
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007844 cfgerr++;
7845 }
7846 else if (target->table.size == 0) {
7847 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007848 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007849 cfgerr++;
7850 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007851 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007852 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007853 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007854 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007855 cfgerr++;
7856 }
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007857 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007858 free(trule->arg.trk_ctr.table.n);
7859 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007860 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreau9ba2dcc2010-06-14 21:04:55 +02007861 * to pass a list of counters to track and allocate them right here using
7862 * stktable_alloc_data_type().
7863 */
7864 }
7865 }
7866
Willy Tarreau620408f2016-10-21 16:37:51 +02007867 /* find the target table for 'tcp-request' layer 5 rules */
7868 list_for_each_entry(trule, &curproxy->tcp_req.l5_rules, list) {
7869 struct proxy *target;
7870
7871 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
7872 continue;
7873
7874 if (trule->arg.trk_ctr.table.n)
7875 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
7876 else
7877 target = curproxy;
7878
7879 if (!target) {
7880 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
7881 curproxy->id, trule->arg.trk_ctr.table.n,
7882 tcp_trk_idx(trule->action));
7883 cfgerr++;
7884 }
7885 else if (target->table.size == 0) {
7886 Alert("Proxy '%s': table '%s' used but not configured.\n",
7887 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
7888 cfgerr++;
7889 }
7890 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
7891 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
7892 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
7893 tcp_trk_idx(trule->action));
7894 cfgerr++;
7895 }
7896 else {
7897 free(trule->arg.trk_ctr.table.n);
7898 trule->arg.trk_ctr.table.t = &target->table;
7899 /* Note: if we decide to enhance the track-sc syntax, we may be able
7900 * to pass a list of counters to track and allocate them right here using
7901 * stktable_alloc_data_type().
7902 */
7903 }
7904 }
7905
Willy Tarreaud1f96522010-08-03 19:34:32 +02007906 /* find the target table for 'tcp-request' layer 6 rules */
7907 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
7908 struct proxy *target;
7909
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007910 if (trule->action < ACT_ACTION_TRK_SC0 || trule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreaud1f96522010-08-03 19:34:32 +02007911 continue;
7912
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007913 if (trule->arg.trk_ctr.table.n)
7914 target = proxy_tbl_by_name(trule->arg.trk_ctr.table.n);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007915 else
7916 target = curproxy;
7917
7918 if (!target) {
Willy Tarreau56123282010-08-06 19:06:56 +02007919 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007920 curproxy->id, trule->arg.trk_ctr.table.n,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007921 tcp_trk_idx(trule->action));
Willy Tarreaud1f96522010-08-03 19:34:32 +02007922 cfgerr++;
7923 }
7924 else if (target->table.size == 0) {
7925 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007926 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreaud1f96522010-08-03 19:34:32 +02007927 cfgerr++;
7928 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007929 else if (!stktable_compatible_sample(trule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau5f53de72012-12-12 00:25:44 +01007930 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007931 curproxy->id, trule->arg.trk_ctr.table.n ? trule->arg.trk_ctr.table.n : curproxy->id,
Willy Tarreau34c2fb62013-12-02 23:29:05 +01007932 tcp_trk_idx(trule->action));
Willy Tarreau5f53de72012-12-12 00:25:44 +01007933 cfgerr++;
7934 }
Willy Tarreaud1f96522010-08-03 19:34:32 +02007935 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007936 free(trule->arg.trk_ctr.table.n);
7937 trule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau56123282010-08-06 19:06:56 +02007938 /* Note: if we decide to enhance the track-sc syntax, we may be able
Willy Tarreaud1f96522010-08-03 19:34:32 +02007939 * to pass a list of counters to track and allocate them right here using
7940 * stktable_alloc_data_type().
7941 */
7942 }
7943 }
7944
Baptiste Assmanne9544932015-11-03 23:31:35 +01007945 /* parse http-request capture rules to ensure id really exists */
7946 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7947 if (hrqrule->action != ACT_CUSTOM ||
7948 hrqrule->action_ptr != http_action_req_capture_by_id)
7949 continue;
7950
7951 if (hrqrule->arg.capid.idx >= curproxy->nb_req_cap) {
7952 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-request capture rule.\n",
7953 curproxy->id, hrqrule->arg.capid.idx);
7954 cfgerr++;
7955 }
7956 }
7957
7958 /* parse http-response capture rules to ensure id really exists */
7959 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
7960 if (hrqrule->action != ACT_CUSTOM ||
7961 hrqrule->action_ptr != http_action_res_capture_by_id)
7962 continue;
7963
7964 if (hrqrule->arg.capid.idx >= curproxy->nb_rsp_cap) {
7965 Alert("Proxy '%s': unable to find capture id '%d' referenced by http-response capture rule.\n",
7966 curproxy->id, hrqrule->arg.capid.idx);
7967 cfgerr++;
7968 }
7969 }
7970
Willy Tarreau09448f72014-06-25 18:12:15 +02007971 /* find the target table for 'http-request' layer 7 rules */
7972 list_for_each_entry(hrqrule, &curproxy->http_req_rules, list) {
7973 struct proxy *target;
7974
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02007975 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
Willy Tarreau09448f72014-06-25 18:12:15 +02007976 continue;
7977
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007978 if (hrqrule->arg.trk_ctr.table.n)
7979 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
Willy Tarreau09448f72014-06-25 18:12:15 +02007980 else
7981 target = curproxy;
7982
7983 if (!target) {
7984 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007985 curproxy->id, hrqrule->arg.trk_ctr.table.n,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007986 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02007987 cfgerr++;
7988 }
7989 else if (target->table.size == 0) {
7990 Alert("Proxy '%s': table '%s' used but not configured.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007991 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
Willy Tarreau09448f72014-06-25 18:12:15 +02007992 cfgerr++;
7993 }
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007994 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
Willy Tarreau09448f72014-06-25 18:12:15 +02007995 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02007996 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
Ruoshan Huange4edc6b2016-07-14 15:07:45 +08007997 http_trk_idx(hrqrule->action));
7998 cfgerr++;
7999 }
8000 else {
8001 free(hrqrule->arg.trk_ctr.table.n);
8002 hrqrule->arg.trk_ctr.table.t = &target->table;
8003 /* Note: if we decide to enhance the track-sc syntax, we may be able
8004 * to pass a list of counters to track and allocate them right here using
8005 * stktable_alloc_data_type().
8006 */
8007 }
8008 }
8009
8010 /* find the target table for 'http-response' layer 7 rules */
8011 list_for_each_entry(hrqrule, &curproxy->http_res_rules, list) {
8012 struct proxy *target;
8013
8014 if (hrqrule->action < ACT_ACTION_TRK_SC0 || hrqrule->action > ACT_ACTION_TRK_SCMAX)
8015 continue;
8016
8017 if (hrqrule->arg.trk_ctr.table.n)
8018 target = proxy_tbl_by_name(hrqrule->arg.trk_ctr.table.n);
8019 else
8020 target = curproxy;
8021
8022 if (!target) {
8023 Alert("Proxy '%s': unable to find table '%s' referenced by track-sc%d.\n",
8024 curproxy->id, hrqrule->arg.trk_ctr.table.n,
8025 http_trk_idx(hrqrule->action));
8026 cfgerr++;
8027 }
8028 else if (target->table.size == 0) {
8029 Alert("Proxy '%s': table '%s' used but not configured.\n",
8030 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id);
8031 cfgerr++;
8032 }
8033 else if (!stktable_compatible_sample(hrqrule->arg.trk_ctr.expr, target->table.type)) {
8034 Alert("Proxy '%s': stick-table '%s' uses a type incompatible with the 'track-sc%d' rule.\n",
8035 curproxy->id, hrqrule->arg.trk_ctr.table.n ? hrqrule->arg.trk_ctr.table.n : curproxy->id,
8036 http_trk_idx(hrqrule->action));
Willy Tarreau09448f72014-06-25 18:12:15 +02008037 cfgerr++;
8038 }
8039 else {
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008040 free(hrqrule->arg.trk_ctr.table.n);
8041 hrqrule->arg.trk_ctr.table.t = &target->table;
Willy Tarreau09448f72014-06-25 18:12:15 +02008042 /* Note: if we decide to enhance the track-sc syntax, we may be able
8043 * to pass a list of counters to track and allocate them right here using
8044 * stktable_alloc_data_type().
8045 */
8046 }
8047 }
8048
Willy Tarreaub3dc39d2014-04-28 22:06:57 +02008049 /* move any "block" rules at the beginning of the http-request rules */
8050 if (!LIST_ISEMPTY(&curproxy->block_rules)) {
8051 /* insert block_rules into http_req_rules at the beginning */
8052 curproxy->block_rules.p->n = curproxy->http_req_rules.n;
8053 curproxy->http_req_rules.n->p = curproxy->block_rules.p;
8054 curproxy->block_rules.n->p = &curproxy->http_req_rules;
8055 curproxy->http_req_rules.n = curproxy->block_rules.n;
8056 LIST_INIT(&curproxy->block_rules);
8057 }
8058
Emeric Brun32da3c42010-09-23 18:39:19 +02008059 if (curproxy->table.peers.name) {
8060 struct peers *curpeers = peers;
8061
8062 for (curpeers = peers; curpeers; curpeers = curpeers->next) {
8063 if (strcmp(curpeers->id, curproxy->table.peers.name) == 0) {
8064 free((void *)curproxy->table.peers.name);
Willy Tarreau973ca492013-01-17 21:34:52 +01008065 curproxy->table.peers.p = curpeers;
Emeric Brun32da3c42010-09-23 18:39:19 +02008066 break;
8067 }
8068 }
8069
8070 if (!curpeers) {
8071 Alert("Proxy '%s': unable to find sync peers '%s'.\n",
8072 curproxy->id, curproxy->table.peers.name);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008073 free((void *)curproxy->table.peers.name);
8074 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008075 cfgerr++;
8076 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02008077 else if (curpeers->state == PR_STSTOPPED) {
8078 /* silently disable this peers section */
8079 curproxy->table.peers.p = NULL;
8080 }
Emeric Brun32da3c42010-09-23 18:39:19 +02008081 else if (!curpeers->peers_fe) {
Willy Tarreau122541c2011-09-07 21:24:49 +02008082 Alert("Proxy '%s': unable to find local peer '%s' in peers section '%s'.\n",
8083 curproxy->id, localpeer, curpeers->id);
Willy Tarreaud66bf962011-10-28 14:16:49 +02008084 curproxy->table.peers.p = NULL;
Emeric Brun32da3c42010-09-23 18:39:19 +02008085 cfgerr++;
8086 }
8087 }
8088
Simon Horman9dc49962015-01-30 11:22:59 +09008089
8090 if (curproxy->email_alert.mailers.name) {
8091 struct mailers *curmailers = mailers;
8092
8093 for (curmailers = mailers; curmailers; curmailers = curmailers->next) {
8094 if (strcmp(curmailers->id, curproxy->email_alert.mailers.name) == 0) {
8095 free(curproxy->email_alert.mailers.name);
8096 curproxy->email_alert.mailers.m = curmailers;
8097 curmailers->users++;
8098 break;
8099 }
8100 }
8101
8102 if (!curmailers) {
8103 Alert("Proxy '%s': unable to find mailers '%s'.\n",
8104 curproxy->id, curproxy->email_alert.mailers.name);
8105 free_email_alert(curproxy);
8106 cfgerr++;
8107 }
8108 }
8109
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008110 if (curproxy->uri_auth && !(curproxy->uri_auth->flags & ST_CONVDONE) &&
Willy Tarreauff011f22011-01-06 17:51:27 +01008111 !LIST_ISEMPTY(&curproxy->uri_auth->http_req_rules) &&
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008112 (curproxy->uri_auth->userlist || curproxy->uri_auth->auth_realm )) {
8113 Alert("%s '%s': stats 'auth'/'realm' and 'http-request' can't be used at the same time.\n",
8114 "proxy", curproxy->id);
8115 cfgerr++;
8116 goto out_uri_auth_compat;
8117 }
8118
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008119 if (curproxy->uri_auth && curproxy->uri_auth->userlist && !(curproxy->uri_auth->flags & ST_CONVDONE)) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008120 const char *uri_auth_compat_req[10];
Thierry FOURNIERa28a9422015-08-04 19:35:46 +02008121 struct act_rule *rule;
Willy Tarreau95fa4692010-02-01 13:05:50 +01008122 int i = 0;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008123
Willy Tarreau95fa4692010-02-01 13:05:50 +01008124 /* build the ACL condition from scratch. We're relying on anonymous ACLs for that */
8125 uri_auth_compat_req[i++] = "auth";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008126
8127 if (curproxy->uri_auth->auth_realm) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008128 uri_auth_compat_req[i++] = "realm";
8129 uri_auth_compat_req[i++] = curproxy->uri_auth->auth_realm;
8130 }
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008131
Willy Tarreau95fa4692010-02-01 13:05:50 +01008132 uri_auth_compat_req[i++] = "unless";
8133 uri_auth_compat_req[i++] = "{";
8134 uri_auth_compat_req[i++] = "http_auth(.internal-stats-userlist)";
8135 uri_auth_compat_req[i++] = "}";
8136 uri_auth_compat_req[i++] = "";
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008137
Willy Tarreauff011f22011-01-06 17:51:27 +01008138 rule = parse_http_req_cond(uri_auth_compat_req, "internal-stats-auth-compat", 0, curproxy);
8139 if (!rule) {
Willy Tarreau95fa4692010-02-01 13:05:50 +01008140 cfgerr++;
8141 break;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008142 }
8143
Willy Tarreauff011f22011-01-06 17:51:27 +01008144 LIST_ADDQ(&curproxy->uri_auth->http_req_rules, &rule->list);
Willy Tarreau95fa4692010-02-01 13:05:50 +01008145
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008146 if (curproxy->uri_auth->auth_realm) {
8147 free(curproxy->uri_auth->auth_realm);
8148 curproxy->uri_auth->auth_realm = NULL;
8149 }
Krzysztof Piotr Oledzki329f74d2010-02-22 20:27:23 +01008150
8151 curproxy->uri_auth->flags |= ST_CONVDONE;
Krzysztof Piotr Oledzki8c8bd452010-01-29 19:29:32 +01008152 }
8153out_uri_auth_compat:
8154
Dragan Dosen43885c72015-10-01 13:18:13 +02008155 /* check whether we have a log server that uses RFC5424 log format */
Dragan Dosen1322d092015-09-22 16:05:32 +02008156 list_for_each_entry(tmplogsrv, &curproxy->logsrvs, list) {
Dragan Dosen43885c72015-10-01 13:18:13 +02008157 if (tmplogsrv->format == LOG_FORMAT_RFC5424) {
8158 if (!curproxy->conf.logformat_sd_string) {
8159 /* set the default logformat_sd_string */
8160 curproxy->conf.logformat_sd_string = default_rfc5424_sd_log_format;
8161 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008162 break;
Dragan Dosen1322d092015-09-22 16:05:32 +02008163 }
Dragan Dosen1322d092015-09-22 16:05:32 +02008164 }
Dragan Dosen68d2e3a2015-09-19 22:35:44 +02008165
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008166 /* compile the log format */
8167 if (!(curproxy->cap & PR_CAP_FE)) {
Willy Tarreau62a61232013-04-12 18:13:46 +02008168 if (curproxy->conf.logformat_string != default_http_log_format &&
8169 curproxy->conf.logformat_string != default_tcp_log_format &&
8170 curproxy->conf.logformat_string != clf_http_log_format)
8171 free(curproxy->conf.logformat_string);
8172 curproxy->conf.logformat_string = NULL;
8173 free(curproxy->conf.lfs_file);
8174 curproxy->conf.lfs_file = NULL;
8175 curproxy->conf.lfs_line = 0;
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008176
8177 if (curproxy->conf.logformat_sd_string != default_rfc5424_sd_log_format)
8178 free(curproxy->conf.logformat_sd_string);
8179 curproxy->conf.logformat_sd_string = NULL;
8180 free(curproxy->conf.lfsd_file);
8181 curproxy->conf.lfsd_file = NULL;
8182 curproxy->conf.lfsd_line = 0;
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008183 }
8184
Willy Tarreau62a61232013-04-12 18:13:46 +02008185 if (curproxy->conf.logformat_string) {
8186 curproxy->conf.args.ctx = ARGC_LOG;
8187 curproxy->conf.args.file = curproxy->conf.lfs_file;
8188 curproxy->conf.args.line = curproxy->conf.lfs_line;
8189 parse_logformat_string(curproxy->conf.logformat_string, curproxy, &curproxy->logformat, LOG_OPT_MANDATORY,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008190 SMP_VAL_FE_LOG_END, curproxy->conf.lfs_file, curproxy->conf.lfs_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008191 curproxy->conf.args.file = NULL;
8192 curproxy->conf.args.line = 0;
8193 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008194
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008195 if (curproxy->conf.logformat_sd_string) {
8196 curproxy->conf.args.ctx = ARGC_LOGSD;
8197 curproxy->conf.args.file = curproxy->conf.lfsd_file;
8198 curproxy->conf.args.line = curproxy->conf.lfsd_line;
8199 parse_logformat_string(curproxy->conf.logformat_sd_string, curproxy, &curproxy->logformat_sd, LOG_OPT_MANDATORY,
8200 SMP_VAL_FE_LOG_END, curproxy->conf.lfsd_file, curproxy->conf.lfsd_line);
8201 add_to_logformat_list(NULL, NULL, LF_SEPARATOR, &curproxy->logformat_sd);
8202 curproxy->conf.args.file = NULL;
8203 curproxy->conf.args.line = 0;
8204 }
8205
Willy Tarreau62a61232013-04-12 18:13:46 +02008206 if (curproxy->conf.uniqueid_format_string) {
8207 curproxy->conf.args.ctx = ARGC_UIF;
8208 curproxy->conf.args.file = curproxy->conf.uif_file;
8209 curproxy->conf.args.line = curproxy->conf.uif_line;
Thierry FOURNIERd048d8b2014-03-13 16:46:18 +01008210 parse_logformat_string(curproxy->conf.uniqueid_format_string, curproxy, &curproxy->format_unique_id, LOG_OPT_HTTP,
Godbachd9722032014-12-18 15:44:58 +08008211 (curproxy->cap & PR_CAP_FE) ? SMP_VAL_FE_HRQ_HDR : SMP_VAL_BE_HRQ_HDR,
Thierry FOURNIEReeaa9512014-02-11 14:00:19 +01008212 curproxy->conf.uif_file, curproxy->conf.uif_line);
Willy Tarreau62a61232013-04-12 18:13:46 +02008213 curproxy->conf.args.file = NULL;
8214 curproxy->conf.args.line = 0;
8215 }
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008216
Thierry FOURNIER9eec0a62014-01-22 18:38:02 +01008217 /* only now we can check if some args remain unresolved.
8218 * This must be done after the users and groups resolution.
8219 */
Willy Tarreaua4312fa2013-04-02 16:34:32 +02008220 cfgerr += smp_resolve_args(curproxy);
8221 if (!cfgerr)
8222 cfgerr += acl_find_targets(curproxy);
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +01008223
Willy Tarreau2738a142006-07-08 17:28:09 +02008224 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008225 (((curproxy->cap & PR_CAP_FE) && !curproxy->timeout.client) ||
Willy Tarreaud825eef2007-05-12 22:35:00 +02008226 ((curproxy->cap & PR_CAP_BE) && (curproxy->srv) &&
Willy Tarreauce887fd2012-05-12 12:50:00 +02008227 (!curproxy->timeout.connect ||
8228 (!curproxy->timeout.server && (curproxy->mode == PR_MODE_HTTP || !curproxy->timeout.tunnel)))))) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008229 Warning("config : missing timeouts for %s '%s'.\n"
Willy Tarreau2738a142006-07-08 17:28:09 +02008230 " | While not properly invalid, you will certainly encounter various problems\n"
8231 " | with such a configuration. To fix this, please ensure that all following\n"
Willy Tarreau0f68eac2008-01-20 23:25:06 +01008232 " | timeouts are set to a non-zero value: 'client', 'connect', 'server'.\n",
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008233 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008234 err_code |= ERR_WARN;
Willy Tarreau2738a142006-07-08 17:28:09 +02008235 }
Willy Tarreauf3c69202006-07-09 16:42:34 +02008236
Willy Tarreau1fa31262007-12-03 00:36:16 +01008237 /* Historically, the tarpit and queue timeouts were inherited from contimeout.
8238 * We must still support older configurations, so let's find out whether those
8239 * parameters have been set or must be copied from contimeouts.
8240 */
8241 if (curproxy != &defproxy) {
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008242 if (!curproxy->timeout.tarpit ||
8243 curproxy->timeout.tarpit == defproxy.timeout.tarpit) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008244 /* tarpit timeout not set. We search in the following order:
8245 * default.tarpit, curr.connect, default.connect.
8246 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008247 if (defproxy.timeout.tarpit)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008248 curproxy->timeout.tarpit = defproxy.timeout.tarpit;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008249 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008250 curproxy->timeout.tarpit = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008251 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008252 curproxy->timeout.tarpit = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008253 }
8254 if ((curproxy->cap & PR_CAP_BE) &&
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008255 (!curproxy->timeout.queue ||
8256 curproxy->timeout.queue == defproxy.timeout.queue)) {
Willy Tarreau1fa31262007-12-03 00:36:16 +01008257 /* queue timeout not set. We search in the following order:
8258 * default.queue, curr.connect, default.connect.
8259 */
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008260 if (defproxy.timeout.queue)
Willy Tarreau1fa31262007-12-03 00:36:16 +01008261 curproxy->timeout.queue = defproxy.timeout.queue;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008262 else if (curproxy->timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008263 curproxy->timeout.queue = curproxy->timeout.connect;
Willy Tarreau0c303ee2008-07-07 00:09:58 +02008264 else if (defproxy.timeout.connect)
Willy Tarreaud7c30f92007-12-03 01:38:36 +01008265 curproxy->timeout.queue = defproxy.timeout.connect;
Willy Tarreau1fa31262007-12-03 00:36:16 +01008266 }
8267 }
8268
Willy Tarreau1620ec32011-08-06 17:05:02 +02008269 if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
Willy Tarreau137325d2010-02-01 16:38:17 +01008270 curproxy->check_len = sizeof(sslv3_client_hello_pkt) - 1;
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008271 curproxy->check_req = malloc(curproxy->check_len);
Willy Tarreau137325d2010-02-01 16:38:17 +01008272 memcpy(curproxy->check_req, sslv3_client_hello_pkt, curproxy->check_len);
Willy Tarreauf3c69202006-07-09 16:42:34 +02008273 }
8274
Willy Tarreau215663d2014-06-13 18:30:23 +02008275 if (!LIST_ISEMPTY(&curproxy->tcpcheck_rules) &&
8276 (curproxy->options2 & PR_O2_CHK_ANY) != PR_O2_TCPCHK_CHK) {
8277 Warning("config : %s '%s' uses tcp-check rules without 'option tcp-check', so the rules are ignored.\n",
8278 proxy_type_str(curproxy), curproxy->id);
8279 err_code |= ERR_WARN;
8280 }
8281
Willy Tarreau193b8c62012-11-22 00:17:38 +01008282 /* ensure that cookie capture length is not too large */
8283 if (curproxy->capture_len >= global.tune.cookie_len) {
8284 Warning("config : truncating capture length to %d bytes for %s '%s'.\n",
8285 global.tune.cookie_len - 1, proxy_type_str(curproxy), curproxy->id);
8286 err_code |= ERR_WARN;
8287 curproxy->capture_len = global.tune.cookie_len - 1;
8288 }
8289
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008290 /* The small pools required for the capture lists */
Willy Tarreau9a54e132012-03-24 08:33:05 +01008291 if (curproxy->nb_req_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008292 curproxy->req_cap_pool = create_pool("ptrcap",
8293 curproxy->nb_req_cap * sizeof(char *),
8294 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008295 }
8296
8297 if (curproxy->nb_rsp_cap) {
Willy Tarreaud9ed3d22014-06-13 12:23:06 +02008298 curproxy->rsp_cap_pool = create_pool("ptrcap",
8299 curproxy->nb_rsp_cap * sizeof(char *),
8300 MEM_F_SHARED);
Willy Tarreau9a54e132012-03-24 08:33:05 +01008301 }
Willy Tarreaucf7f3202007-05-13 22:46:04 +02008302
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02008303 switch (curproxy->load_server_state_from_file) {
8304 case PR_SRV_STATE_FILE_UNSPEC:
8305 curproxy->load_server_state_from_file = PR_SRV_STATE_FILE_NONE;
8306 break;
8307 case PR_SRV_STATE_FILE_GLOBAL:
8308 if (!global.server_state_file) {
8309 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",
8310 curproxy->id);
8311 err_code |= ERR_WARN;
8312 }
8313 break;
8314 }
8315
Willy Tarreaubaaee002006-06-26 02:48:02 +02008316 /* first, we will invert the servers list order */
8317 newsrv = NULL;
8318 while (curproxy->srv) {
8319 struct server *next;
8320
8321 next = curproxy->srv->next;
8322 curproxy->srv->next = newsrv;
8323 newsrv = curproxy->srv;
8324 if (!next)
8325 break;
8326 curproxy->srv = next;
8327 }
8328
Willy Tarreau17edc812014-01-03 12:14:34 +01008329 /* Check that no server name conflicts. This causes trouble in the stats.
8330 * We only emit a warning for the first conflict affecting each server,
8331 * in order to avoid combinatory explosion if all servers have the same
8332 * name. We do that only for servers which do not have an explicit ID,
8333 * because these IDs were made also for distinguishing them and we don't
8334 * want to annoy people who correctly manage them.
8335 */
8336 for (newsrv = curproxy->srv; newsrv; newsrv = newsrv->next) {
8337 struct server *other_srv;
8338
8339 if (newsrv->puid)
8340 continue;
8341
8342 for (other_srv = curproxy->srv; other_srv && other_srv != newsrv; other_srv = other_srv->next) {
8343 if (!other_srv->puid && strcmp(other_srv->id, newsrv->id) == 0) {
8344 Warning("parsing [%s:%d] : %s '%s', another server named '%s' was defined without an explicit ID at line %d, this is not recommended.\n",
8345 newsrv->conf.file, newsrv->conf.line,
8346 proxy_type_str(curproxy), curproxy->id,
8347 newsrv->id, other_srv->conf.line);
8348 break;
8349 }
8350 }
8351 }
8352
Willy Tarreaudd701652010-05-25 23:03:02 +02008353 /* assign automatic UIDs to servers which don't have one yet */
8354 next_id = 1;
8355 newsrv = curproxy->srv;
8356 while (newsrv != NULL) {
8357 if (!newsrv->puid) {
8358 /* server ID not set, use automatic numbering with first
8359 * spare entry starting with next_svid.
8360 */
8361 next_id = get_next_id(&curproxy->conf.used_server_id, next_id);
8362 newsrv->conf.id.key = newsrv->puid = next_id;
8363 eb32_insert(&curproxy->conf.used_server_id, &newsrv->conf.id);
8364 }
8365 next_id++;
8366 newsrv = newsrv->next;
8367 }
8368
Willy Tarreau20697042007-11-15 23:26:18 +01008369 curproxy->lbprm.wmult = 1; /* default weight multiplier */
Willy Tarreau5dc2fa62007-11-19 19:10:18 +01008370 curproxy->lbprm.wdiv = 1; /* default weight divider */
Willy Tarreaubaaee002006-06-26 02:48:02 +02008371
Willy Tarreau62c3be22012-01-20 13:12:32 +01008372 /*
8373 * If this server supports a maxconn parameter, it needs a dedicated
8374 * tasks to fill the emptied slots when a connection leaves.
8375 * Also, resolve deferred tracking dependency if needed.
8376 */
8377 newsrv = curproxy->srv;
8378 while (newsrv != NULL) {
8379 if (newsrv->minconn > newsrv->maxconn) {
8380 /* Only 'minconn' was specified, or it was higher than or equal
8381 * to 'maxconn'. Let's turn this into maxconn and clean it, as
8382 * this will avoid further useless expensive computations.
8383 */
8384 newsrv->maxconn = newsrv->minconn;
8385 } else if (newsrv->maxconn && !newsrv->minconn) {
8386 /* minconn was not specified, so we set it to maxconn */
8387 newsrv->minconn = newsrv->maxconn;
8388 }
8389
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008390#ifdef USE_OPENSSL
Emeric Brun94324a42012-10-11 14:00:19 +02008391 if (newsrv->use_ssl || newsrv->check.use_ssl)
8392 cfgerr += ssl_sock_prepare_srv_ctx(newsrv, curproxy);
Emeric Brun01f8e2f2012-05-18 16:02:00 +02008393#endif /* USE_OPENSSL */
Emeric Brun94324a42012-10-11 14:00:19 +02008394
Willy Tarreau2f075e92013-12-03 11:11:34 +01008395 /* set the check type on the server */
8396 newsrv->check.type = curproxy->options2 & PR_O2_CHK_ANY;
8397
Willy Tarreau62c3be22012-01-20 13:12:32 +01008398 if (newsrv->trackit) {
8399 struct proxy *px;
Willy Tarreau32091232014-05-16 13:52:00 +02008400 struct server *srv, *loop;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008401 char *pname, *sname;
8402
8403 pname = newsrv->trackit;
8404 sname = strrchr(pname, '/');
8405
8406 if (sname)
8407 *sname++ = '\0';
8408 else {
8409 sname = pname;
8410 pname = NULL;
8411 }
8412
8413 if (pname) {
Willy Tarreau9e0bb102015-05-26 11:24:42 +02008414 px = proxy_be_by_name(pname);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008415 if (!px) {
8416 Alert("config : %s '%s', server '%s': unable to find required proxy '%s' for tracking.\n",
8417 proxy_type_str(curproxy), curproxy->id,
8418 newsrv->id, pname);
8419 cfgerr++;
8420 goto next_srv;
8421 }
8422 } else
8423 px = curproxy;
8424
8425 srv = findserver(px, sname);
8426 if (!srv) {
8427 Alert("config : %s '%s', server '%s': unable to find required server '%s' for tracking.\n",
8428 proxy_type_str(curproxy), curproxy->id,
8429 newsrv->id, sname);
8430 cfgerr++;
8431 goto next_srv;
8432 }
8433
Willy Tarreau32091232014-05-16 13:52:00 +02008434 if (!(srv->check.state & CHK_ST_CONFIGURED) &&
8435 !(srv->agent.state & CHK_ST_CONFIGURED) &&
8436 !srv->track && !srv->trackit) {
Willy Tarreau62c3be22012-01-20 13:12:32 +01008437 Alert("config : %s '%s', server '%s': unable to use %s/%s for "
Willy Tarreau32091232014-05-16 13:52:00 +02008438 "tracking as it does not have any check nor agent enabled.\n",
8439 proxy_type_str(curproxy), curproxy->id,
8440 newsrv->id, px->id, srv->id);
8441 cfgerr++;
8442 goto next_srv;
8443 }
8444
8445 for (loop = srv->track; loop && loop != newsrv; loop = loop->track);
8446
8447 if (loop) {
8448 Alert("config : %s '%s', server '%s': unable to track %s/%s as it "
8449 "belongs to a tracking chain looping back to %s/%s.\n",
8450 proxy_type_str(curproxy), curproxy->id,
8451 newsrv->id, px->id, srv->id, px->id, loop->id);
Willy Tarreau62c3be22012-01-20 13:12:32 +01008452 cfgerr++;
8453 goto next_srv;
8454 }
8455
8456 if (curproxy != px &&
8457 (curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
8458 Alert("config : %s '%s', server '%s': unable to use %s/%s for"
8459 "tracking: disable-on-404 option inconsistency.\n",
8460 proxy_type_str(curproxy), curproxy->id,
8461 newsrv->id, px->id, srv->id);
8462 cfgerr++;
8463 goto next_srv;
8464 }
8465
Willy Tarreau62c3be22012-01-20 13:12:32 +01008466 newsrv->track = srv;
Willy Tarreau1a53a3a2013-12-11 15:27:05 +01008467 newsrv->tracknext = srv->trackers;
8468 srv->trackers = newsrv;
Willy Tarreau62c3be22012-01-20 13:12:32 +01008469
8470 free(newsrv->trackit);
8471 newsrv->trackit = NULL;
8472 }
Baptiste Assmanna68ca962015-04-14 01:15:08 +02008473
8474 /*
8475 * resolve server's resolvers name and update the resolvers pointer
8476 * accordingly
8477 */
8478 if (newsrv->resolvers_id) {
8479 struct dns_resolvers *curr_resolvers;
8480 int found;
8481
8482 found = 0;
8483 list_for_each_entry(curr_resolvers, &dns_resolvers, list) {
8484 if (!strcmp(curr_resolvers->id, newsrv->resolvers_id)) {
8485 found = 1;
8486 break;
8487 }
8488 }
8489
8490 if (!found) {
8491 Alert("config : %s '%s', server '%s': unable to find required resolvers '%s'\n",
8492 proxy_type_str(curproxy), curproxy->id,
8493 newsrv->id, newsrv->resolvers_id);
8494 cfgerr++;
8495 } else {
8496 free(newsrv->resolvers_id);
8497 newsrv->resolvers_id = NULL;
8498 if (newsrv->resolution)
8499 newsrv->resolution->resolvers = curr_resolvers;
8500 }
8501 }
8502 else {
8503 /* if no resolvers section associated to this server
8504 * we can clean up the associated resolution structure
8505 */
8506 if (newsrv->resolution) {
8507 free(newsrv->resolution->hostname_dn);
8508 newsrv->resolution->hostname_dn = NULL;
8509 free(newsrv->resolution);
8510 newsrv->resolution = NULL;
8511 }
8512 }
8513
Willy Tarreau62c3be22012-01-20 13:12:32 +01008514 next_srv:
8515 newsrv = newsrv->next;
8516 }
8517
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008518 /* We have to initialize the server lookup mechanism depending
8519 * on what LB algorithm was choosen.
8520 */
8521
8522 curproxy->lbprm.algo &= ~(BE_LB_LKUP | BE_LB_PROP_DYN);
8523 switch (curproxy->lbprm.algo & BE_LB_KIND) {
8524 case BE_LB_KIND_RR:
Willy Tarreau9757a382009-10-03 12:56:50 +02008525 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_RR_STATIC) {
8526 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8527 init_server_map(curproxy);
8528 } else {
8529 curproxy->lbprm.algo |= BE_LB_LKUP_RRTREE | BE_LB_PROP_DYN;
8530 fwrr_init_server_groups(curproxy);
8531 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008532 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008533
Willy Tarreau3ebb1162012-02-13 16:57:44 +01008534 case BE_LB_KIND_CB:
Willy Tarreauf09c6602012-02-13 17:12:08 +01008535 if ((curproxy->lbprm.algo & BE_LB_PARM) == BE_LB_CB_LC) {
8536 curproxy->lbprm.algo |= BE_LB_LKUP_LCTREE | BE_LB_PROP_DYN;
8537 fwlc_init_server_tree(curproxy);
8538 } else {
8539 curproxy->lbprm.algo |= BE_LB_LKUP_FSTREE | BE_LB_PROP_DYN;
8540 fas_init_server_tree(curproxy);
8541 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008542 break;
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008543
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008544 case BE_LB_KIND_HI:
Willy Tarreau6b2e11b2009-10-01 07:52:15 +02008545 if ((curproxy->lbprm.algo & BE_LB_HASH_TYPE) == BE_LB_HASH_CONS) {
8546 curproxy->lbprm.algo |= BE_LB_LKUP_CHTREE | BE_LB_PROP_DYN;
8547 chash_init_server_tree(curproxy);
8548 } else {
8549 curproxy->lbprm.algo |= BE_LB_LKUP_MAP;
8550 init_server_map(curproxy);
8551 }
Willy Tarreauf3e49f92009-10-03 12:21:20 +02008552 break;
8553 }
Willy Tarreaubaaee002006-06-26 02:48:02 +02008554
8555 if (curproxy->options & PR_O_LOGASAP)
8556 curproxy->to_log &= ~LW_BYTES;
8557
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008558 if ((curproxy->mode == PR_MODE_TCP || curproxy->mode == PR_MODE_HTTP) &&
Dragan Dosen0b85ece2015-09-25 19:17:44 +02008559 (curproxy->cap & PR_CAP_FE) && LIST_ISEMPTY(&curproxy->logsrvs) &&
8560 (!LIST_ISEMPTY(&curproxy->logformat) || !LIST_ISEMPTY(&curproxy->logformat_sd))) {
Willy Tarreaue7ded1f2009-08-09 10:11:45 +02008561 Warning("config : log format ignored for %s '%s' since it has no log address.\n",
8562 proxy_type_str(curproxy), curproxy->id);
8563 err_code |= ERR_WARN;
8564 }
8565
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008566 if (curproxy->mode != PR_MODE_HTTP) {
8567 int optnum;
8568
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008569 if (curproxy->uri_auth) {
8570 Warning("config : 'stats' statement ignored for %s '%s' as it requires HTTP mode.\n",
8571 proxy_type_str(curproxy), curproxy->id);
8572 err_code |= ERR_WARN;
8573 curproxy->uri_auth = NULL;
8574 }
8575
Willy Tarreau87cf5142011-08-19 22:57:24 +02008576 if (curproxy->options & (PR_O_FWDFOR | PR_O_FF_ALWAYS)) {
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008577 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8578 "forwardfor", proxy_type_str(curproxy), curproxy->id);
8579 err_code |= ERR_WARN;
Willy Tarreau87cf5142011-08-19 22:57:24 +02008580 curproxy->options &= ~(PR_O_FWDFOR | PR_O_FF_ALWAYS);
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008581 }
8582
8583 if (curproxy->options & PR_O_ORGTO) {
8584 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8585 "originalto", proxy_type_str(curproxy), curproxy->id);
8586 err_code |= ERR_WARN;
8587 curproxy->options &= ~PR_O_ORGTO;
8588 }
8589
8590 for (optnum = 0; cfg_opts[optnum].name; optnum++) {
8591 if (cfg_opts[optnum].mode == PR_MODE_HTTP &&
8592 (curproxy->cap & cfg_opts[optnum].cap) &&
8593 (curproxy->options & cfg_opts[optnum].val)) {
8594 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8595 cfg_opts[optnum].name, proxy_type_str(curproxy), curproxy->id);
8596 err_code |= ERR_WARN;
8597 curproxy->options &= ~cfg_opts[optnum].val;
8598 }
8599 }
8600
8601 for (optnum = 0; cfg_opts2[optnum].name; optnum++) {
8602 if (cfg_opts2[optnum].mode == PR_MODE_HTTP &&
8603 (curproxy->cap & cfg_opts2[optnum].cap) &&
8604 (curproxy->options2 & cfg_opts2[optnum].val)) {
8605 Warning("config : 'option %s' ignored for %s '%s' as it requires HTTP mode.\n",
8606 cfg_opts2[optnum].name, proxy_type_str(curproxy), curproxy->id);
8607 err_code |= ERR_WARN;
8608 curproxy->options2 &= ~cfg_opts2[optnum].val;
8609 }
8610 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008611
Willy Tarreau29fbe512015-08-20 19:35:14 +02008612#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008613 if (curproxy->conn_src.bind_hdr_occ) {
8614 curproxy->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008615 Warning("config : %s '%s' : ignoring use of header %s as source IP in non-HTTP mode.\n",
Willy Tarreauef9a3602012-12-08 22:29:20 +01008616 proxy_type_str(curproxy), curproxy->id, curproxy->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008617 err_code |= ERR_WARN;
8618 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008619#endif
Willy Tarreaue24fdfb2010-03-25 07:22:56 +01008620 }
8621
Willy Tarreaubaaee002006-06-26 02:48:02 +02008622 /*
Willy Tarreau21d2af32008-02-14 20:25:24 +01008623 * ensure that we're not cross-dressing a TCP server into HTTP.
8624 */
8625 newsrv = curproxy->srv;
8626 while (newsrv != NULL) {
Willy Tarreau0cec3312011-10-31 13:49:26 +01008627 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->rdr_len) {
Willy Tarreau915e1eb2009-06-22 15:48:36 +02008628 Alert("config : %s '%s' : server cannot have cookie or redirect prefix in non-HTTP mode.\n",
8629 proxy_type_str(curproxy), curproxy->id);
Willy Tarreaubb925012009-07-23 13:36:36 +02008630 cfgerr++;
Willy Tarreau21d2af32008-02-14 20:25:24 +01008631 }
Willy Tarreaubce70882009-09-07 11:51:47 +02008632
Willy Tarreau0cec3312011-10-31 13:49:26 +01008633 if ((curproxy->mode != PR_MODE_HTTP) && newsrv->cklen) {
8634 Warning("config : %s '%s' : ignoring cookie for server '%s' as HTTP mode is disabled.\n",
8635 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8636 err_code |= ERR_WARN;
8637 }
8638
Willy Tarreauc93cd162014-05-13 15:54:22 +02008639 if ((newsrv->flags & SRV_F_MAPPORTS) && (curproxy->options2 & PR_O2_RDPC_PRST)) {
Willy Tarreau82ffa392013-08-13 17:19:08 +02008640 Warning("config : %s '%s' : RDP cookie persistence will not work for server '%s' because it lacks an explicit port number.\n",
8641 proxy_type_str(curproxy), curproxy->id, newsrv->id);
8642 err_code |= ERR_WARN;
8643 }
8644
Willy Tarreau29fbe512015-08-20 19:35:14 +02008645#if defined(CONFIG_HAP_TRANSPARENT)
Willy Tarreauef9a3602012-12-08 22:29:20 +01008646 if (curproxy->mode != PR_MODE_HTTP && newsrv->conn_src.bind_hdr_occ) {
8647 newsrv->conn_src.bind_hdr_occ = 0;
Willy Tarreaubce70882009-09-07 11:51:47 +02008648 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 +01008649 proxy_type_str(curproxy), curproxy->id, newsrv->id, newsrv->conn_src.bind_hdr_name);
Willy Tarreaubce70882009-09-07 11:51:47 +02008650 err_code |= ERR_WARN;
8651 }
Willy Tarreauefa5f512010-03-30 20:13:29 +02008652#endif
Willy Tarreau21d2af32008-02-14 20:25:24 +01008653 newsrv = newsrv->next;
8654 }
8655
Willy Tarreaue42bd962014-09-16 16:21:19 +02008656 /* check if we have a frontend with "tcp-request content" looking at L7
8657 * with no inspect-delay
8658 */
8659 if ((curproxy->cap & PR_CAP_FE) && !curproxy->tcp_req.inspect_delay) {
8660 list_for_each_entry(trule, &curproxy->tcp_req.inspect_rules, list) {
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008661 if (trule->action == ACT_TCP_CAPTURE &&
Thierry FOURNIERd0d65ae2015-08-04 08:21:12 +02008662 !(trule->arg.cap.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008663 break;
Thierry FOURNIER0ea5c7f2015-08-05 19:05:19 +02008664 if ((trule->action >= ACT_ACTION_TRK_SC0 && trule->action <= ACT_ACTION_TRK_SCMAX) &&
Thierry FOURNIER5ec63e02015-08-04 09:09:48 +02008665 !(trule->arg.trk_ctr.expr->fetch->val & SMP_VAL_FE_SES_ACC))
Willy Tarreaue42bd962014-09-16 16:21:19 +02008666 break;
8667 }
8668
8669 if (&trule->list != &curproxy->tcp_req.inspect_rules) {
8670 Warning("config : %s '%s' : some 'tcp-request content' rules explicitly depending on request"
8671 " contents were found in a frontend without any 'tcp-request inspect-delay' setting."
8672 " This means that these rules will randomly find their contents. This can be fixed by"
8673 " setting the tcp-request inspect-delay.\n",
8674 proxy_type_str(curproxy), curproxy->id);
8675 err_code |= ERR_WARN;
8676 }
8677 }
8678
Christopher Fauletd7c91962015-04-30 11:48:27 +02008679 /* Check filter configuration, if any */
8680 cfgerr += flt_check(curproxy);
8681
Willy Tarreauc1a21672009-08-16 22:37:44 +02008682 if (curproxy->cap & PR_CAP_FE) {
Willy Tarreau050536d2012-10-04 08:47:34 +02008683 if (!curproxy->accept)
8684 curproxy->accept = frontend_accept;
Willy Tarreau81f9aa32010-06-01 17:45:26 +02008685
Willy Tarreauc1a21672009-08-16 22:37:44 +02008686 if (curproxy->tcp_req.inspect_delay ||
8687 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
Willy Tarreaufb356202010-08-03 14:02:05 +02008688 curproxy->fe_req_ana |= AN_REQ_INSPECT_FE;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008689
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008690 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008691 curproxy->fe_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_PROCESS_FE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008692 curproxy->fe_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_FE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008693 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008694
8695 /* both TCP and HTTP must check switching rules */
8696 curproxy->fe_req_ana |= AN_REQ_SWITCHING_RULES;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008697
8698 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008699 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008700 curproxy->fe_req_ana |= AN_FLT_ALL_FE;
8701 curproxy->fe_rsp_ana |= AN_FLT_ALL_FE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008702 if (curproxy->mode == PR_MODE_HTTP) {
8703 curproxy->fe_req_ana |= AN_FLT_HTTP_HDRS;
8704 curproxy->fe_rsp_ana |= AN_FLT_HTTP_HDRS;
8705 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008706 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008707 }
8708
8709 if (curproxy->cap & PR_CAP_BE) {
Willy Tarreaufb356202010-08-03 14:02:05 +02008710 if (curproxy->tcp_req.inspect_delay ||
8711 !LIST_ISEMPTY(&curproxy->tcp_req.inspect_rules))
8712 curproxy->be_req_ana |= AN_REQ_INSPECT_BE;
8713
Emeric Brun97679e72010-09-23 17:56:44 +02008714 if (!LIST_ISEMPTY(&curproxy->tcp_rep.inspect_rules))
8715 curproxy->be_rsp_ana |= AN_RES_INSPECT;
8716
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008717 if (curproxy->mode == PR_MODE_HTTP) {
Willy Tarreauc1a21672009-08-16 22:37:44 +02008718 curproxy->be_req_ana |= AN_REQ_WAIT_HTTP | AN_REQ_HTTP_INNER | AN_REQ_HTTP_PROCESS_BE;
Willy Tarreaub37c27e2009-10-18 22:53:08 +02008719 curproxy->be_rsp_ana |= AN_RES_WAIT_HTTP | AN_RES_HTTP_PROCESS_BE;
Willy Tarreau4e5b8282009-08-16 22:57:50 +02008720 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008721
8722 /* If the backend does requires RDP cookie persistence, we have to
8723 * enable the corresponding analyser.
8724 */
8725 if (curproxy->options2 & PR_O2_RDPC_PRST)
8726 curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
Christopher Fauletd7c91962015-04-30 11:48:27 +02008727
8728 /* Add filters analyzers if needed */
Christopher Faulet443ea1a2016-02-04 13:40:26 +01008729 if (!LIST_ISEMPTY(&curproxy->filter_configs)) {
Christopher Fauletd7c91962015-04-30 11:48:27 +02008730 curproxy->be_req_ana |= AN_FLT_ALL_BE;
8731 curproxy->be_rsp_ana |= AN_FLT_ALL_BE;
Christopher Faulet309c6412015-12-02 09:57:32 +01008732 if (curproxy->mode == PR_MODE_HTTP) {
8733 curproxy->be_req_ana |= AN_FLT_HTTP_HDRS;
8734 curproxy->be_rsp_ana |= AN_FLT_HTTP_HDRS;
8735 }
Christopher Fauletd7c91962015-04-30 11:48:27 +02008736 }
Willy Tarreauc1a21672009-08-16 22:37:44 +02008737 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008738 }
8739
8740 /***********************************************************/
8741 /* At this point, target names have already been resolved. */
8742 /***********************************************************/
8743
8744 /* Check multi-process mode compatibility */
8745
8746 if (global.nbproc > 1 && global.stats_fe) {
8747 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8748 unsigned long mask;
8749
8750 mask = nbits(global.nbproc);
8751 if (global.stats_fe->bind_proc)
8752 mask &= global.stats_fe->bind_proc;
8753
8754 if (bind_conf->bind_proc)
8755 mask &= bind_conf->bind_proc;
8756
8757 /* stop here if more than one process is used */
David Carliere6c39412015-07-02 07:00:17 +00008758 if (my_popcountl(mask) > 1)
Willy Tarreau419ead82014-09-16 13:41:21 +02008759 break;
8760 }
8761 if (&bind_conf->by_fe != &global.stats_fe->conf.bind) {
8762 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");
8763 }
8764 }
8765
8766 /* Make each frontend inherit bind-process from its listeners when not specified. */
8767 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8768 if (curproxy->bind_proc)
8769 continue;
8770
8771 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8772 unsigned long mask;
8773
Willy Tarreaue428b082015-05-04 21:57:58 +02008774 mask = bind_conf->bind_proc ? bind_conf->bind_proc : nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008775 curproxy->bind_proc |= mask;
8776 }
8777
8778 if (!curproxy->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008779 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008780 }
8781
8782 if (global.stats_fe) {
8783 list_for_each_entry(bind_conf, &global.stats_fe->conf.bind, by_fe) {
8784 unsigned long mask;
8785
Cyril Bonté06181952016-02-24 00:14:54 +01008786 mask = bind_conf->bind_proc ? bind_conf->bind_proc : 0;
Willy Tarreau419ead82014-09-16 13:41:21 +02008787 global.stats_fe->bind_proc |= mask;
8788 }
8789 if (!global.stats_fe->bind_proc)
Willy Tarreaue428b082015-05-04 21:57:58 +02008790 global.stats_fe->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008791 }
8792
Willy Tarreauacbe8ab2014-10-01 20:50:17 +02008793 /* propagate bindings from frontends to backends. Don't do it if there
8794 * are any fatal errors as we must not call it with unresolved proxies.
8795 */
8796 if (!cfgerr) {
8797 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8798 if (curproxy->cap & PR_CAP_FE)
8799 propagate_processes(curproxy, NULL);
8800 }
Willy Tarreau419ead82014-09-16 13:41:21 +02008801 }
8802
8803 /* Bind each unbound backend to all processes when not specified. */
8804 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8805 if (curproxy->bind_proc)
8806 continue;
Willy Tarreaue428b082015-05-04 21:57:58 +02008807 curproxy->bind_proc = nbits(global.nbproc);
Willy Tarreau419ead82014-09-16 13:41:21 +02008808 }
8809
8810 /*******************************************************/
8811 /* At this step, all proxies have a non-null bind_proc */
8812 /*******************************************************/
8813
8814 /* perform the final checks before creating tasks */
8815
8816 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
8817 struct listener *listener;
8818 unsigned int next_id;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008819
Emeric Brunc52962f2012-11-15 18:28:02 +01008820#ifdef USE_OPENSSL
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008821 /* Configure SSL for each bind line.
8822 * Note: if configuration fails at some point, the ->ctx member
8823 * remains NULL so that listeners can later detach.
8824 */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008825 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008826 int alloc_ctx;
8827
Emeric Brunc52962f2012-11-15 18:28:02 +01008828 if (!bind_conf->is_ssl) {
8829 if (bind_conf->default_ctx) {
8830 Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n",
8831 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
8832 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008833 continue;
Emeric Brunc52962f2012-11-15 18:28:02 +01008834 }
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008835 if (!bind_conf->default_ctx) {
Emeric Brunfc0421f2012-09-07 17:30:07 +02008836 Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008837 curproxy->id, bind_conf->arg, bind_conf->file, bind_conf->line);
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008838 cfgerr++;
8839 continue;
8840 }
8841
Emeric Brun8dc60392014-05-09 13:52:00 +02008842 alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global.tune.sslprivatecache && (global.nbproc > 1)) ? 1 : 0);
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008843 if (alloc_ctx < 0) {
Emeric Brun93ee2492014-05-09 14:01:48 +02008844 if (alloc_ctx == SHCTX_E_INIT_LOCK)
8845 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");
8846 else
Emeric Bruncaa19cc2014-05-07 16:10:18 +02008847 Alert("Unable to allocate SSL session cache.\n");
Emeric Brun93ee2492014-05-09 14:01:48 +02008848 cfgerr++;
8849 continue;
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008850 }
8851
Emeric Brunfc0421f2012-09-07 17:30:07 +02008852 /* initialize all certificate contexts */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008853 cfgerr += ssl_sock_prepare_all_ctx(bind_conf, curproxy);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008854
8855 /* initialize CA variables if the certificates generation is enabled */
8856 cfgerr += ssl_sock_load_ca(bind_conf, curproxy);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008857 }
Emeric Brunc52962f2012-11-15 18:28:02 +01008858#endif /* USE_OPENSSL */
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008859
Willy Tarreaue6b98942007-10-29 01:09:36 +01008860 /* adjust this proxy's listeners */
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008861 next_id = 1;
Willy Tarreau4348fad2012-09-20 16:48:07 +02008862 list_for_each_entry(listener, &curproxy->conf.listeners, by_fe) {
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008863 int nbproc;
8864
8865 nbproc = my_popcountl(curproxy->bind_proc &
Cyril Bonté4920d702016-04-15 07:58:43 +02008866 (listener->bind_conf->bind_proc ? listener->bind_conf->bind_proc : curproxy->bind_proc) &
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008867 nbits(global.nbproc));
8868
8869 if (!nbproc) /* no intersection between listener and frontend */
8870 nbproc = 1;
8871
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008872 if (!listener->luid) {
8873 /* listener ID not set, use automatic numbering with first
8874 * spare entry starting with next_luid.
8875 */
8876 next_id = get_next_id(&curproxy->conf.used_listener_id, next_id);
8877 listener->conf.id.key = listener->luid = next_id;
8878 eb32_insert(&curproxy->conf.used_listener_id, &listener->conf.id);
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008879 }
Krzysztof Piotr Oledzkidf5cb9f2010-02-05 20:58:27 +01008880 next_id++;
Willy Tarreau53fb4ae2009-10-04 23:04:08 +02008881
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008882 /* enable separate counters */
8883 if (curproxy->options2 & PR_O2_SOCKSTAT) {
Vincent Bernat3c2f2f22016-04-03 13:48:42 +02008884 listener->counters = calloc(1, sizeof(struct licounters));
Willy Tarreau19d14ef2012-10-29 16:51:55 +01008885 if (!listener->name)
8886 memprintf(&listener->name, "sock-%d", listener->luid);
Krzysztof Piotr Oledzkiaeebf9b2009-10-04 15:43:17 +02008887 }
Willy Tarreau81796be2012-09-22 19:11:47 +02008888
Willy Tarreaue6b98942007-10-29 01:09:36 +01008889 if (curproxy->options & PR_O_TCP_NOLING)
8890 listener->options |= LI_O_NOLINGER;
Willy Tarreau32368ce2012-09-06 11:10:55 +02008891 if (!listener->maxconn)
8892 listener->maxconn = curproxy->maxconn;
8893 if (!listener->backlog)
8894 listener->backlog = curproxy->backlog;
Willy Tarreau16a21472012-11-19 12:39:59 +01008895 if (!listener->maxaccept)
8896 listener->maxaccept = global.tune.maxaccept ? global.tune.maxaccept : 64;
8897
8898 /* we want to have an optimal behaviour on single process mode to
8899 * maximize the work at once, but in multi-process we want to keep
8900 * some fairness between processes, so we target half of the max
8901 * number of events to be balanced over all the processes the proxy
8902 * is bound to. Rememeber that maxaccept = -1 must be kept as it is
8903 * used to disable the limit.
8904 */
8905 if (listener->maxaccept > 0) {
8906 if (nbproc > 1)
8907 listener->maxaccept = (listener->maxaccept + 1) / 2;
8908 listener->maxaccept = (listener->maxaccept + nbproc - 1) / nbproc;
8909 }
8910
Willy Tarreau9903f0e2015-04-04 18:50:31 +02008911 listener->accept = session_accept_fd;
Willy Tarreau87b09662015-04-03 00:22:06 +02008912 listener->handler = process_stream;
Willy Tarreauc1a21672009-08-16 22:37:44 +02008913 listener->analysers |= curproxy->fe_req_ana;
Willy Tarreau10b688f2015-03-13 16:43:12 +01008914 listener->default_target = curproxy->default_target;
Willy Tarreau3bc13772008-12-07 11:50:35 +01008915
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008916 if (!LIST_ISEMPTY(&curproxy->tcp_req.l4_rules))
Willy Tarreau7d9736f2016-10-21 16:34:21 +02008917 listener->options |= LI_O_TCP_L4_RULES;
Willy Tarreaua5c0ab22010-05-31 10:30:33 +02008918
Willy Tarreau620408f2016-10-21 16:37:51 +02008919 if (!LIST_ISEMPTY(&curproxy->tcp_req.l5_rules))
8920 listener->options |= LI_O_TCP_L5_RULES;
8921
Willy Tarreaude3041d2010-05-31 10:56:17 +02008922 if (curproxy->mon_mask.s_addr)
8923 listener->options |= LI_O_CHK_MONNET;
8924
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008925 /* smart accept mode is automatic in HTTP mode */
8926 if ((curproxy->options2 & PR_O2_SMARTACC) ||
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008927 ((curproxy->mode == PR_MODE_HTTP || listener->bind_conf->is_ssl) &&
Willy Tarreau9ea05a72009-06-14 12:07:01 +02008928 !(curproxy->no_options2 & PR_O2_SMARTACC)))
8929 listener->options |= LI_O_NOQUICKACK;
Willy Tarreaue6b98942007-10-29 01:09:36 +01008930 }
8931
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008932 /* Release unused SSL configs */
8933 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
8934 if (bind_conf->is_ssl)
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008935 continue;
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008936#ifdef USE_OPENSSL
Christopher Faulet31af49d2015-06-09 17:29:50 +02008937 ssl_sock_free_ca(bind_conf);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008938 ssl_sock_free_all_ctx(bind_conf);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008939 free(bind_conf->ca_file);
Christopher Faulet31af49d2015-06-09 17:29:50 +02008940 free(bind_conf->ca_sign_file);
8941 free(bind_conf->ca_sign_pass);
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008942 free(bind_conf->ciphers);
Emeric Brun2b58d042012-09-20 17:10:03 +02008943 free(bind_conf->ecdhe);
Emeric Brunfb510ea2012-10-05 12:00:26 +02008944 free(bind_conf->crl_file);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008945 if(bind_conf->keys_ref) {
8946 free(bind_conf->keys_ref->filename);
8947 free(bind_conf->keys_ref->tlskeys);
William Lallemand7bba4cc2016-05-20 17:28:07 +02008948 LIST_DEL(&bind_conf->keys_ref->list);
Nenad Merdanovic146defa2015-05-09 08:46:00 +02008949 free(bind_conf->keys_ref);
8950 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008951#endif /* USE_OPENSSL */
Willy Tarreau2a65ff02012-09-13 17:54:29 +02008952 }
Willy Tarreauf5ae8f72012-09-07 16:58:00 +02008953
Willy Tarreau7c0ffd22016-04-14 11:47:38 +02008954 if (my_popcountl(curproxy->bind_proc & nbits(global.nbproc)) > 1) {
Willy Tarreau102df612014-05-07 23:56:38 +02008955 if (curproxy->uri_auth) {
Willy Tarreaueb791e02014-09-16 15:11:04 +02008956 int count, maxproc = 0;
8957
8958 list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) {
David Carliere6c39412015-07-02 07:00:17 +00008959 count = my_popcountl(bind_conf->bind_proc);
Willy Tarreaueb791e02014-09-16 15:11:04 +02008960 if (count > maxproc)
8961 maxproc = count;
8962 }
8963 /* backends have 0, frontends have 1 or more */
8964 if (maxproc != 1)
8965 Warning("Proxy '%s': in multi-process mode, stats will be"
8966 " limited to process assigned to the current request.\n",
8967 curproxy->id);
8968
Willy Tarreau102df612014-05-07 23:56:38 +02008969 if (!LIST_ISEMPTY(&curproxy->uri_auth->admin_rules)) {
8970 Warning("Proxy '%s': stats admin will not work correctly in multi-process mode.\n",
8971 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008972 }
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008973 }
Willy Tarreau102df612014-05-07 23:56:38 +02008974 if (!LIST_ISEMPTY(&curproxy->sticking_rules)) {
8975 Warning("Proxy '%s': sticking rules will not work correctly in multi-process mode.\n",
8976 curproxy->id);
Cyril Bonté02ff8ef2010-12-14 22:48:49 +01008977 }
8978 }
Willy Tarreau918ff602011-07-25 16:33:49 +02008979
8980 /* create the task associated with the proxy */
8981 curproxy->task = task_new();
8982 if (curproxy->task) {
8983 curproxy->task->context = curproxy;
8984 curproxy->task->process = manage_proxy;
8985 /* no need to queue, it will be done automatically if some
8986 * listener gets limited.
8987 */
8988 curproxy->task->expire = TICK_ETERNITY;
8989 } else {
8990 Alert("Proxy '%s': no more memory when trying to allocate the management task\n",
8991 curproxy->id);
8992 cfgerr++;
8993 }
Willy Tarreaub369a042014-09-16 13:21:03 +02008994 }
8995
Willy Tarreaufbb78422011-06-05 15:38:35 +02008996 /* automatically compute fullconn if not set. We must not do it in the
8997 * loop above because cross-references are not yet fully resolved.
8998 */
8999 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9000 /* If <fullconn> is not set, let's set it to 10% of the sum of
9001 * the possible incoming frontend's maxconns.
9002 */
9003 if (!curproxy->fullconn && (curproxy->cap & PR_CAP_BE)) {
9004 struct proxy *fe;
9005 int total = 0;
9006
9007 /* sum up the number of maxconns of frontends which
9008 * reference this backend at least once or which are
9009 * the same one ('listen').
9010 */
9011 for (fe = proxy; fe; fe = fe->next) {
9012 struct switching_rule *rule;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009013 int found = 0;
9014
9015 if (!(fe->cap & PR_CAP_FE))
9016 continue;
9017
9018 if (fe == curproxy) /* we're on a "listen" instance */
9019 found = 1;
9020
9021 if (fe->defbe.be == curproxy) /* "default_backend" */
9022 found = 1;
9023
9024 /* check if a "use_backend" rule matches */
9025 if (!found) {
9026 list_for_each_entry(rule, &fe->switching_rules, list) {
Bertrand Jacquin702d44f2013-11-19 11:43:06 +01009027 if (!rule->dynamic && rule->be.backend == curproxy) {
Willy Tarreaufbb78422011-06-05 15:38:35 +02009028 found = 1;
9029 break;
9030 }
9031 }
9032 }
9033
Willy Tarreaufbb78422011-06-05 15:38:35 +02009034 /* now we've checked all possible ways to reference a backend
9035 * from a frontend.
9036 */
Willy Tarreaufbb78422011-06-05 15:38:35 +02009037 if (!found)
9038 continue;
9039 total += fe->maxconn;
Willy Tarreaufbb78422011-06-05 15:38:35 +02009040 }
Willy Tarreaufbb78422011-06-05 15:38:35 +02009041 /* we have the sum of the maxconns in <total>. We only
9042 * keep 10% of that sum to set the default fullconn, with
9043 * a hard minimum of 1 (to avoid a divide by zero).
9044 */
9045 curproxy->fullconn = (total + 9) / 10;
9046 if (!curproxy->fullconn)
9047 curproxy->fullconn = 1;
9048 }
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01009049 }
9050
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009051 /*
9052 * Recount currently required checks.
9053 */
9054
9055 for (curproxy=proxy; curproxy; curproxy=curproxy->next) {
9056 int optnum;
9057
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009058 for (optnum = 0; cfg_opts[optnum].name; optnum++)
9059 if (curproxy->options & cfg_opts[optnum].val)
9060 global.last_checks |= cfg_opts[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009061
Willy Tarreau66aa61f2009-01-18 21:44:07 +01009062 for (optnum = 0; cfg_opts2[optnum].name; optnum++)
9063 if (curproxy->options2 & cfg_opts2[optnum].val)
9064 global.last_checks |= cfg_opts2[optnum].checks;
Krzysztof Oledzki336d4752007-12-25 02:40:22 +01009065 }
9066
Willy Tarreau0fca4832015-05-01 19:12:05 +02009067 /* compute the required process bindings for the peers */
9068 for (curproxy = proxy; curproxy; curproxy = curproxy->next)
9069 if (curproxy->table.peers.p)
9070 curproxy->table.peers.p->peers_fe->bind_proc |= curproxy->bind_proc;
9071
Willy Tarreau122541c2011-09-07 21:24:49 +02009072 if (peers) {
9073 struct peers *curpeers = peers, **last;
9074 struct peer *p, *pb;
9075
Willy Tarreau1e273012015-05-01 19:15:17 +02009076 /* Remove all peers sections which don't have a valid listener,
9077 * which are not used by any table, or which are bound to more
9078 * than one process.
Willy Tarreau122541c2011-09-07 21:24:49 +02009079 */
9080 last = &peers;
9081 while (*last) {
9082 curpeers = *last;
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009083
9084 if (curpeers->state == PR_STSTOPPED) {
9085 /* the "disabled" keyword was present */
9086 if (curpeers->peers_fe)
9087 stop_proxy(curpeers->peers_fe);
9088 curpeers->peers_fe = NULL;
9089 }
9090 else if (!curpeers->peers_fe) {
9091 Warning("Removing incomplete section 'peers %s' (no peer named '%s').\n",
9092 curpeers->id, localpeer);
9093 }
David Carliere6c39412015-07-02 07:00:17 +00009094 else if (my_popcountl(curpeers->peers_fe->bind_proc) != 1) {
Willy Tarreau1e273012015-05-01 19:15:17 +02009095 /* either it's totally stopped or too much used */
9096 if (curpeers->peers_fe->bind_proc) {
9097 Alert("Peers section '%s': peers referenced by sections "
Willy Tarreau64c57222015-05-04 21:48:51 +02009098 "running in different processes (%d different ones). "
9099 "Check global.nbproc and all tables' bind-process "
David Carliere6c39412015-07-02 07:00:17 +00009100 "settings.\n", curpeers->id, my_popcountl(curpeers->peers_fe->bind_proc));
Willy Tarreau1e273012015-05-01 19:15:17 +02009101 cfgerr++;
9102 }
9103 stop_proxy(curpeers->peers_fe);
9104 curpeers->peers_fe = NULL;
9105 }
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009106 else {
Emeric Brunb3971ab2015-05-12 18:49:09 +02009107 peers_init_sync(curpeers);
Willy Tarreau122541c2011-09-07 21:24:49 +02009108 last = &curpeers->next;
9109 continue;
9110 }
9111
Willy Tarreau77e4bd12015-05-01 20:02:17 +02009112 /* clean what has been detected above */
Willy Tarreau122541c2011-09-07 21:24:49 +02009113 p = curpeers->remote;
9114 while (p) {
9115 pb = p->next;
9116 free(p->id);
9117 free(p);
9118 p = pb;
9119 }
9120
9121 /* Destroy and unlink this curpeers section.
9122 * Note: curpeers is backed up into *last.
9123 */
9124 free(curpeers->id);
9125 curpeers = curpeers->next;
9126 free(*last);
9127 *last = curpeers;
9128 }
9129 }
9130
Willy Tarreau6866f3f2015-05-01 19:09:08 +02009131 /* initialize stick-tables on backend capable proxies. This must not
9132 * be done earlier because the data size may be discovered while parsing
9133 * other proxies.
9134 */
9135 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9136 if (curproxy->state == PR_STSTOPPED)
9137 continue;
9138
9139 if (!stktable_init(&curproxy->table)) {
9140 Alert("Proxy '%s': failed to initialize stick-table.\n", curproxy->id);
9141 cfgerr++;
9142 }
9143 }
9144
Simon Horman0d16a402015-01-30 11:22:58 +09009145 if (mailers) {
9146 struct mailers *curmailers = mailers, **last;
9147 struct mailer *m, *mb;
9148
9149 /* Remove all mailers sections which don't have a valid listener.
9150 * This can happen when a mailers section is never referenced.
9151 */
9152 last = &mailers;
9153 while (*last) {
9154 curmailers = *last;
9155 if (curmailers->users) {
9156 last = &curmailers->next;
9157 continue;
9158 }
9159
9160 Warning("Removing incomplete section 'mailers %s'.\n",
9161 curmailers->id);
9162
9163 m = curmailers->mailer_list;
9164 while (m) {
9165 mb = m->next;
9166 free(m->id);
9167 free(m);
9168 m = mb;
9169 }
9170
9171 /* Destroy and unlink this curmailers section.
9172 * Note: curmailers is backed up into *last.
9173 */
9174 free(curmailers->id);
9175 curmailers = curmailers->next;
9176 free(*last);
9177 *last = curmailers;
9178 }
9179 }
9180
Baptiste Assmanne11cfcd2015-08-19 16:44:03 +02009181 /* Update server_state_file_name to backend name if backend is supposed to use
9182 * a server-state file locally defined and none has been provided */
9183 for (curproxy = proxy; curproxy; curproxy = curproxy->next) {
9184 if (curproxy->load_server_state_from_file == PR_SRV_STATE_FILE_LOCAL &&
9185 curproxy->server_state_file_name == NULL)
9186 curproxy->server_state_file_name = strdup(curproxy->id);
9187 }
9188
Willy Tarreau34eb6712011-10-24 18:15:04 +02009189 pool2_hdr_idx = create_pool("hdr_idx",
Willy Tarreauac1932d2011-10-24 19:14:41 +02009190 global.tune.max_http_hdr * sizeof(struct hdr_idx_elem),
Willy Tarreau34eb6712011-10-24 18:15:04 +02009191 MEM_F_SHARED);
9192
Willy Tarreaubb925012009-07-23 13:36:36 +02009193 if (cfgerr > 0)
9194 err_code |= ERR_ALERT | ERR_FATAL;
9195 out:
9196 return err_code;
Willy Tarreaubaaee002006-06-26 02:48:02 +02009197}
9198
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009199/*
9200 * Registers the CFG keyword list <kwl> as a list of valid keywords for next
9201 * parsing sessions.
9202 */
9203void cfg_register_keywords(struct cfg_kw_list *kwl)
9204{
9205 LIST_ADDQ(&cfg_keywords.list, &kwl->list);
9206}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009207
Willy Tarreau5b2c3362008-07-09 19:39:06 +02009208/*
9209 * Unregisters the CFG keyword list <kwl> from the list of valid keywords.
9210 */
9211void cfg_unregister_keywords(struct cfg_kw_list *kwl)
9212{
9213 LIST_DEL(&kwl->list);
9214 LIST_INIT(&kwl->list);
9215}
Willy Tarreaubaaee002006-06-26 02:48:02 +02009216
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009217/* this function register new section in the haproxy configuration file.
9218 * <section_name> is the name of this new section and <section_parser>
9219 * is the called parser. If two section declaration have the same name,
9220 * only the first declared is used.
9221 */
9222int cfg_register_section(char *section_name,
9223 int (*section_parser)(const char *, int, char **, int))
9224{
9225 struct cfg_section *cs;
9226
Willy Tarreau5e4261b2016-05-17 16:16:09 +02009227 list_for_each_entry(cs, &sections, list) {
9228 if (strcmp(cs->section_name, section_name) == 0) {
9229 Alert("register section '%s': already registered.\n", section_name);
9230 return 0;
9231 }
9232 }
9233
Thierry FOURNIERfa45f1d2014-03-18 13:54:18 +01009234 cs = calloc(1, sizeof(*cs));
9235 if (!cs) {
9236 Alert("register section '%s': out of memory.\n", section_name);
9237 return 0;
9238 }
9239
9240 cs->section_name = section_name;
9241 cs->section_parser = section_parser;
9242
9243 LIST_ADDQ(&sections, &cs->list);
9244
9245 return 1;
9246}
9247
Willy Tarreaubaaee002006-06-26 02:48:02 +02009248/*
David Carlier845efb52015-09-25 11:49:18 +01009249 * free all config section entries
9250 */
9251void cfg_unregister_sections(void)
9252{
9253 struct cfg_section *cs, *ics;
9254
9255 list_for_each_entry_safe(cs, ics, &sections, list) {
9256 LIST_DEL(&cs->list);
9257 free(cs);
9258 }
9259}
9260
Willy Tarreau659fbf02016-05-26 17:55:28 +02009261__attribute__((constructor))
9262static void cfgparse_init(void)
9263{
9264 /* Register internal sections */
9265 cfg_register_section("listen", cfg_parse_listen);
9266 cfg_register_section("frontend", cfg_parse_listen);
9267 cfg_register_section("backend", cfg_parse_listen);
9268 cfg_register_section("defaults", cfg_parse_listen);
9269 cfg_register_section("global", cfg_parse_global);
9270 cfg_register_section("userlist", cfg_parse_users);
9271 cfg_register_section("peers", cfg_parse_peers);
9272 cfg_register_section("mailers", cfg_parse_mailers);
9273 cfg_register_section("namespace_list", cfg_parse_netns);
9274 cfg_register_section("resolvers", cfg_parse_resolvers);
9275}
9276
David Carlier845efb52015-09-25 11:49:18 +01009277/*
Willy Tarreaubaaee002006-06-26 02:48:02 +02009278 * Local variables:
9279 * c-indent-level: 8
9280 * c-basic-offset: 8
9281 * End:
9282 */